体系结构之设计模式在设计原则中的应用
一、数据保护
1.
网站建设哪家好,找创新互联!专注于网页设计、网站建设、微信开发、小程序设计、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了丰县免费建站欢迎大家使用!
二、OCP(开闭原则)的手段
所谓OCP即指对扩展开放(当新需求出现的时候,可以通过扩展现有模型达到目的),对修改关闭(对已有的二进制代码,不允许进行修改)。
实现OCP原则的关键是抽象与封装。利用抽象封装完成对需求可能发生变更的部分进行处理,具体处理手段如下:
1.使用多态的方式
做一个继承树。此方案针对会发生修改但不是很严重的地方,让需求扩展的实体继承已经存在的实体。
2.使用继承与组合联合的方式
例如: 装饰者模式、策略模式、状态模式、桥模式
3.延迟绑定:
运行时注册:
使用Event style或Observer pattern实现运行时注册的方式,当需要进行扩展时,就让扩展的方法监听某个事件,事件发生时这个方式就会被调用(service lookup)
配置文件:
使用配置文件进行启动时绑定,将需要修改、扩展的信息写在配置文件中,通过解析配置文件来决定做什么事情(DataDriven)
继承多态方式(LSP)
构件更替:
如果需要修改、扩展,则在加载模块的时候使用修改/扩展的模块,实现加载绑定。一般是将变化的部分写在一个.dll 文件中,变化的时候直接更新.dll 文件。(ReflectiveorMeta-LevelDesign)
预定义协议:
在两个之间预定义协议,然后各个进程可以独立进行变化,只要通信协议不变。
例如TCP/IP等协议(UniformAccess)
4.信息隐藏
下文有详细讲述
5.泛化模块:Interpreter-Driven
6.限制交互路径
迪米特法则:一个对象应该对其他对象有尽可能少的了解
三、一个模块的信息隐藏有哪两种基本类型,各自有哪些典型的处理手段?
1. 每个模块有一个基本的secret——外部的行为和内部隐藏
每个模块隐藏重要的设计决策的实现,只有模块的组成可以了解细节。所有的设计决策都独立于彼此。即一个模块的接口功能与模块内部程序细节的分离。给出功能接口,隐藏功能实现程序的细节
方法:
外观模式Facade pattern
——信息隐藏:用户和部件的子系统之间解耦合,降低耦合
Controller
2. 模块可能有附加的secrets——改变
预期的变更:把变更从模块中分离开来,安排到新的类,方法或者设计单元中.然后封装隔离所有的secret这样其一旦变更,变更不会影响其他程序模块。将要发生变化的程序部分需要进行一个决策。给出需要修改部分的接口,隐藏待修改部分的实现程序细节
方法:
策略模式:将算法从包含其的对象中抽离出来,封装该算法(策略)为一个对象
装饰模式:装饰在不改变类的代码的情况下扩展了一个类的实例的功能
适配器模式:将类的接口转换成另一个client期望的接口,让接口不兼容的类能一起工作
如果上下文也有可变性:用桥接模式
1. 策略模式:将要变更的算法独立出来,按照OCP的方法将其封装起来成为一个对象,同时给这个算法建立一个继承树(为其设置一个接口,让所有这个算法的可能变更的版本实现这个接口)
2. 状态模式: 对象的行为根据状态的变化(属性的取值变化)而变化,将变化的状态独立出来做成一棵继承树,每一个实现的子类都实现了一种状态下的行为。原来的对象包含一 个对状态对象的引用,表示当前的状态,一切行为都使用这个状态对象的行为。(需要由Context和State来处理状态的变化,不要由Client来处 理)
变化来源于内部,即自己做完某件事情后把自己的状态改掉。
3. 桥接模式:
在 抽象和实现需要独立变化的情况下,将抽象和实现做成两个不同的继承树。抽象接口和实现接口是两个完全不同的接口,实现接口一般包含很基本、原始的方法,而 抽象接口包含的是基于原始方法实现的更加高级的方法。在抽象的接口中包含一个对实现对象的引用,抽象对象的方法中需要调用实现对象的方法(抽象接口的方法 基于实现接口的方法)
四、实现共性与可变性有哪些手段?
多态(继承)与聚合
其中多态(继承)适合于1 of N的情况,父类中封装共性部分,子类中封装可变性部分
聚合适合于MofN的情况,whole角色类封装共性部分,part角色类封装可变性部分
1、如果一个对象集之间除共性外,有超过2个的差异行为,如何处理?
做多个策略树
2、如果一个对象集的部分行为组存在差异性,如何处理?
部分行为绑定在一棵策略树
3、如果一个对象集的部分属性(以及依赖于这些属性的方法)存在差异性,如何处理?
把属性和方法做成策略树
4、如果一个对象集的一个行为需要协作对象来完成,但是它们的协作对象存在差异性,如
何处理?
将“调用协作对象”这一过程置于Strategy中,CommandPattern的变体
5、如果一个对象集的行为因为属性的取值而存在差异性,如何处理?
State Pattern
五、中介解耦机制(在解决De-Coupling时,常常使用哪些Indirection的手段)
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、Observer Pattern
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于
它的对象都得到通知并被自动更新
适用场景:
(1)当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
(2)当一个对象必须通知其他对象,而他又不能假定其他对象是谁。换言之,你不希望这
些对象四紧密耦合的。
(3)当一个模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对
象中以使它们可以各自独立的改变和复用。
优点:
灵活性、可变性、复用性得到保证。目标与观察者之间耦合程度降低,实现抽象耦合,允许
独立的改变目标和观察者,可以复用目标对象而无需同时复用其观察者。
支持广播通信,目标者不必知道观察者是谁
缺点:
增加系统复杂程度,对于系统的理解和测试更加困难。
一个观察者的无意的更新可能引起其他观察者的意外的更新,也容易引起更更新错误,而这
种错误难以捕捉。
2、EventStyle
相比ObserverPattern,可以实现对多个事件的监听。即实现对象间多对多的依赖关系。
其他特点同ObserverPattern
3、CommandPattern
意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;请求排
队或记录请求日志,以及支持可撤销的操作。
适用场景:
(1)抽象出待执行的操作以参数化某对象。
(2)在不同的时候制定、排列和执行请求。
(3)通过在实施操作之前将状态存储起来以支持撤销操作。
(4)支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍。
优点:
将调用操作的对象与知道如何实现该操作的对象解耦。
可以将命令存储在栈或队列中以支持请求排队,命令处理模式维护一个历史信息。
可以容易的支持undo和redo操作,但是必须存储额外的状态信息以避免滞后影响问题。
扩展Command对象很容易。
七、特殊类型处理机制
八、对象的创建有哪些常见解决方法
1、简单场景:
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、复杂场景:
(1)场景一:仅仅一个实例允许被创建
使用SingletonPattern,首先将Constructor私有化;声明一个static private的类实例;创建一个publicstatic的getInstance方法使得外部类可以通过此方法获得此类实例。并且此方法如果用于多线程,要注意声明为protected/synchronize以保证线程安全
(2)场景二:实例个数有限制
以singleton为基础进行改进
(3)场景三:一个类不知道它所必须创建的对象的类;一个类希望有他的子类来制定它所创建的对象;类将创建对象这一职责委托给多个帮助子类中的一个,并且希望将哪一个帮助子类作为代理者这一信息局部化
FactoryMethod
(4)场景四:控制子类拓展,子类与父类的算法框架相同,但局部实现方法不同
TemplateMethodPattern
(5)场景五:多个需创建的类实例之间存在类型依赖关系
AbstractFactoryMethod
(6)场景六:实例的创建和初始化很复杂,例如运行时刻制定要实例化的类;初始化时变量值发生变更
PrototypePattern
分享文章:体系结构之设计模式在设计原则中的应用
转载注明:http://azwzsj.com/article/gcsigg.html