- 尽量扩展方法,增加(扩展)行为,不要修改代码
- 抽象化是开闭原则的关键
com.lzb.pricinple.open_close
- 任何基类出现的地方,子类一定可以出现
- 在代码中将一个基类对象替换成子类对象,程序不会产生任何错误和异常,反之则不成立
- 扩展父类功能,不能改变父类原有功能
- 子类可以扩展自己的方法(子类可以胜任父类工作)
- 子类重写父类方法,子类可以扩充入参,不能相同
- 子类重写父类抽象方法,返回值比父类更小
- 面向接口编程
- 高层模块不应该依赖底层模块,两者都应该依赖其抽象。抽象不应该依赖细节,细节应该依赖于抽象
- Spring的依赖注入
- 接口行为尽可能细化
com.lzb.decorator
:装饰者模式(煎饼+鸡蛋+火腿肠):在不改变原始类接口的情况下,对原始类功能进行增强,并且支持多个装饰器的嵌套使用com.lzb.chain
:责任链com.lzb.state
:状态模式- 关于状态机的一个极度确切地描述是它是一个有向图形,由一组节点和一组相应的转移函数组成。状态机通过响应一系列事件而“运行”。每个事件都在属于“当前” 节点的转移函数的控制范围内,其中函数的范围是节点的一个子集。函数返回“下一个”(也许是同一个)节点。这些节点中至少有一个必须是终态。当到达终态,状态机停止。
- 例如订单的状态流转,状态机就是订单,状态是【已审核】、【待支付】、【已支付】等,动作就是【审核】、【支付】、【取消】
com.lzb.strategy
:策略者模式,封装各种算法实现com.lzb.delegate
:委派模式,老板->项目经理->员工com.lzb.adapter
:适配器模式:事后补救策略。提供跟原始类不同的接口,而代理模式、装饰器模式提供的都是跟原始类相同的接口com.lzb.template
:模板模式com.lzb.proxy
:代理模式(动态代理+静态代理):不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能com.lzb.singleton
:单例模式(线程安全)com.lzb.iterator
:迭代器模式com.lzb.facade
:门面模式- 解决易用性,屏蔽复杂性
- 解决性能问题
com.lzb.composition
:- 树状结构的抽象,将单个对象和组合对象看作是树的节点
- 规则树原型
com.lzb.command
:- 调用者->命令(数据和处理逻辑封装为命令对象)->命令实现者,而这三块内容的拆分也是选择适合场景的关键因素(jdk线程池)
com.lzb.observer
:观察者模式(同步、异步)com.lzb.bridge
:桥接模式- “抽象部分”和“实现部分”可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将一个抽象化子类的对象和一个实现化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
- 一个类存在两个(或多个)独立变化的维度,且这两个(或多个)维度都需要独立进行扩展。(2维问题:微信、支付宝支付/指纹、密码、短信验证码验证;Email、手机短信、站内消息/普通、加急、特急)
- 对于那些不希望使用继承或因为多层继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
- 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
- 比如宝马、奔驰、路虎都有手动挡或者自动挡的,如果这样组合就需要6个类,导致笛卡尔乘积,可以把车和引擎抽象成两个独立的个体,而车只面向引擎的抽象,等价于"子类化"引擎,大大减少类的数量,也解决了多重继承的问题
com.lzb.vistor
:访问者模式- 解决的核心事项是,在一个稳定的数据结构下,例如用户信息、雇员信息等,增加易变的业务访问逻辑。为了增强扩展性,将这两部分的业务解耦的一种设计模式。