1.
所谓OCP即指对扩展开放(当新需求出现的时候,可以通过扩展现有模型达到目的),对修改关闭(对已有的二进制代码,不允许进行修改)。
实现OCP原则的关键是抽象与封装。利用抽象封装完成对需求可能发生变更的部分进行处理,具体处理手段如下:
做一个继承树。此方案针对会发生修改但不是很严重的地方,让需求扩展的实体继承已经存在的实体。
例如: 装饰者模式、策略模式、状态模式、桥模式
运行时注册:
使用Event style或Observer pattern实现运行时注册的方式,当需要进行扩展时,就让扩展的方法监听某个事件,事件发生时这个方式就会被调用(service lookup)
配置文件:
使用配置文件进行启动时绑定,将需要修改、扩展的信息写在配置文件中,通过解析配置文件来决定做什么事情(DataDriven)
继承多态方式(LSP)
构件更替:
如果需要修改、扩展,则在加载模块的时候使用修改/扩展的模块,实现加载绑定。一般是将变化的部分写在一个.dll 文件中,变化的时候直接更新.dll 文件。(ReflectiveorMeta-LevelDesign)
预定义协议:
在两个之间预定义协议,然后各个进程可以独立进行变化,只要通信协议不变。
例如TCP/IP等协议(Uniform Access)
下文有详细讲述
变化来源于内部,即自己做完某件事情后把自己的状态改掉。
多态(继承)与聚合
其中多态(继承)适合于1 of N的情况,父类中封装共性部分,子类中封装可变性部分
聚合适合于M of N的情况,whole角色类封装共性部分,part角色类封装可变性部分
1、如果一个对象集之间除共性外,有超过2个的差异行为,如何处理?
做多个策略树
2、如果一个对象集的部分行为组存在差异性,如何处理?
部分行为绑定在一棵策略树
3、如果一个对象集的部分属性(以及依赖于这些属性的方法)存在差异性,如何处理?
把属性和方法做成策略树
4、如果一个对象集的一个行为需要协作对象来完成,但是它们的协作对象存在差异性,如
何处理?
将“调用协作对象”这一过程置于Strategy中,Command Pattern的变体
5、如果一个对象集的行为因为属性的取值而存在差异性,如何处理?
State Pattern
1)避免重复——只做一次:重复往往代表着耦合,修改一部分重复代码表示要修改其他的
2)DIP:Dependency Inversion Principle,依赖倒置原则,即细节应当依赖于抽象,抽象不应当依赖于细节;在要被其他模块implement的模块中定义接口,这是一种去除依赖减少耦合的基本方式
3)继承:共性和差异性
4)设计模式
中介模式
定义封装一组对象交互方式的对象;中介通过避免对象互相显式引用提升了松散耦合;让你独立的差异交互;集中控制
桥接模式
成果:解耦了接口和实现——消除了编译时依赖,改善了可扩展性,对client隐藏了实现细节
1)依赖倒置:如果抽象实体需要依赖于具体实体的话,那么为具体实体做一个接口,抽象实体可以依赖于这个接口,具体实体则实现这个接口
2) 外观模式:Faade是用户和子系统之间的一层间接,它封装子系统的内部实现并对用户提供访问接口,将这二者解耦
3) 代理模式:Proxy是用户和实际实体之间的一层间接,它负责转发用户的请求到实际实体,对实际实体进行访问控制,将这二者解耦
4) 适配器模式:应用中使用了一个接口Target,这个Target的一个实现需 要使用到一个其他实现,但是那个实现与当前的接口不一致。让Target的实现实体聚合一个Adaptee的对象,做成对象Adapter,当用户对 Adapter有请求的时候,Adapter便将请求转发给Adaptee。同时,Adapter还需要实现用户要求的但是在Adaptee没有实现的职 责,不仅仅是转发请求。(client->Adapter->Adaptee)
5) Event-Style事件风格:使用一个事件处理机制,其他模块可以向处理对象提供事件,也可以将自己的方法注册到某个事件,当这个事件发生之后,处理对象会调用注册到这个事件的所有方法,实现事件源和注册方法的解耦
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于
它的对象都得到通知并被自动更新
适用场景:
(1)当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
(2)当一个对象必须通知其他对象,而他又不能假定其他对象是谁。换言之,你不希望这
些对象四紧密耦合的。
(3)当一个模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对
象中以使它们可以各自独立的改变和复用。
优点:
灵活性、可变性、复用性得到保证。目标与观察者之间耦合程度降低,实现抽象耦合,允许
独立的改变目标和观察者,可以复用目标对象而无需同时复用其观察者。
支持广播通信,目标者不必知道观察者是谁
缺点:
增加系统复杂程度,对于系统的理解和测试更加困难。
一个观察者的无意的更新可能引起其他观察者的意外的更新,也容易引起更更新错误,而这
种错误难以捕捉。
相比Observer Pattern,可以实现对多个事件的监听。即实现对象间多对多的依赖关系。
其他特点同Observer Pattern
意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;请求排
队或记录请求日志,以及支持可撤销的操作。
适用场景:
(1)抽象出待执行的操作以参数化某对象。
(2)在不同的时候制定、排列和执行请求。
(3)通过在实施操作之前将状态存储起来以支持撤销操作。
(4)支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
优点:
将调用操作的对象与知道如何实现该操作的对象解耦。
可以将命令存储在栈或队列中以支持请求排队,命令处理模式维护一个历史信息。
可以容易的支持undo和redo操作,但是必须存储额外的状态信息以避免滞后影响问题。
扩展Command对象很容易。
Creator创建者:对于A、B两个对象,在以下情况下A创建B对象:A聚合了B的对象;A包含了B的对象;A记录了B对象的引用;A使用了B的对象;在A中包含初始化B对象的数据
Coupling低耦合:在A聚合、包含、记录、使用B的情况下,如果将创建B对象的职责赋予其他对象,则A需要与其他对象产生多余的耦合
Cohesion高内聚:在A中包含初始化B对象的数据的情况下,则A为信息专家,根据高内聚原则,A应当承担B对象创建的职责
(2)场景二:实例个数有限制
以singleton为基础进行改进
(3)场景三:一个类不知道它所必须创建的对象的类;一个类希望有他的子类来制定它所创建的对象;类将创建对象这一职责委托给多个帮助子类中的一个,并且希望将哪一个帮助子类作为代理者这一信息局部化
Factory Method
(4)场景四:控制子类拓展,子类与父类的算法框架相同,但局部实现方法不同
Template MethodPattern
(5)场景五:多个需创建的类实例之间存在类型依赖关系
Abstract FactoryMethod
(6)场景六:实例的创建和初始化很复杂,例如运行时刻制定要实例化的类;初始化时变量值发生变更
Prototype Pattern
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。