体系结构之设计模式在设计原则中的应用

一、数据保护

1.

二、OCP(开闭原则)的手段


所谓OCP即指对扩展开放(当新需求出现的时候,可以通过扩展现有模型达到目的),对修改关闭(对已有的二进制代码,不允许进行修改)。
实现OCP原则的关键是抽象与封装。利用抽象封装完成对需求可能发生变更的部分进行处理,具体处理手段如下:

1.使用多态的方式

   做一个继承树。此方案针对会发生修改但不是很严重的地方,让需求扩展的实体继承已经存在的实体。

2.使用继承与组合联合的方式

   例如: 装饰者模式、策略模式、状态模式、桥模式

3.延迟绑定:

运行时注册:

使用Event style或Observer pattern实现运行时注册的方式,当需要进行扩展时,就让扩展的方法监听某个事件,事件发生时这个方式就会被调用(service lookup)

配置文件:

使用配置文件进行启动时绑定,将需要修改、扩展的信息写在配置文件中,通过解析配置文件来决定做什么事情(DataDriven)

继承多态方式(LSP)

构件更替:

如果需要修改、扩展,则在加载模块的时候使用修改/扩展的模块,实现加载绑定。一般是将变化的部分写在一个.dll 文件中,变化的时候直接更新.dll 文件。(ReflectiveorMeta-LevelDesign)

预定义协议:

在两个之间预定义协议,然后各个进程可以独立进行变化,只要通信协议不变。

例如TCP/IP等协议(Uniform Access)

4.信息隐藏

下文有详细讲述

5.泛化模块:Interpreter-Driven

6.限制交互路径

迪米特法则:一个对象应该对其他对象有尽可能少的了解


三、一个模块的信息隐藏有哪两种基本类型,各自有哪些典型的处理手段? 

1. 每个模块有一个基本的secret——外部的行为和内部隐藏

每个模块隐藏重要的设计决策的实现,只有模块的组成可以了解细节。所有的设计决策都独立于彼此。一个模块的接口功能与模块内部程序细节的分离给出功能接口,隐藏功能实现程序的细节

方法:

外观模式Facade pattern

——信息隐藏:用户和部件的子系统之间解耦合,降低耦合

Controller

2. 模块可能有附加的secrets——改变

预期的变更:把变更从模块中分离开来,安排到新的类,方法或者设计单元中.然后封装隔离所有的secret这样其一旦变更,变更不会影响其他程序模块。将要发生变化的程序部分需要进行一个决策。给出需要修改部分的接口,隐藏待修改部分的实现程序细节

方法:

策略模式:将算法从包含其的对象中抽离出来,封装该算法(策略)为一个对象

装饰模式:装饰在不改变类的代码的情况下扩展了一个类的实例的功能

适配器模式:将类的接口转换成另一个client期望的接口,让接口不兼容的类能一起工作

 如果上下文也有可变性:用桥接模式

1. 策略模式:将要变更的算法独立出来,按照OCP的方法将其封装起来成为一个对象,同时给这个算法建立一个继承树(为其设置一个接口,让所有这个算法的可能变更的版本实现这个接口)

体系结构之设计模式在设计原则中的应用

2. 状态模式
对象的行为根据状态的变化(属性的取值变化)而变化,将变化的状态独立出来做成一棵继承树,每一个实现的子类都实现了一种状态下的行为。原来的对象包含一
个对状态对象的引用,表示当前的状态,一切行为都使用这个状态对象的行为。(需要由Context和State来处理状态的变化,不要由Client来处
理)

体系结构之设计模式在设计原则中的应用

变化来源于内部,即自己做完某件事情后把自己的状态改掉。

3. 桥接模式:


抽象和实现需要独立变化的情况下,将抽象和实现做成两个不同的继承树。抽象接口和实现接口是两个完全不同的接口,实现接口一般包含很基本、原始的方法,而
抽象接口包含的是基于原始方法实现的更加高级的方法。在抽象的接口中包含一个对实现对象的引用,抽象对象的方法中需要调用实现对象的方法(抽象接口的方法
基于实现接口的方法
体系结构之设计模式在设计原则中的应用  

四、实现共性与可变性有哪些手段?

多态(继承)与聚合
其中多态(继承)适合于1 of N的情况,父类中封装共性部分,子类中封装可变性部分
聚合适合于M of N的情况,whole角色类封装共性部分,part角色类封装可变性部分

1、如果一个对象集之间除共性外,有超过2个的差异行为,如何处理?
    做多个策略树
2、如果一个对象集的部分行为组存在差异性,如何处理?

部分行为绑定在一棵策略树

3、如果一个对象集的部分属性(以及依赖于这些属性的方法)存在差异性,如何处理?

把属性和方法做成策略树

4、如果一个对象集的一个行为需要协作对象来完成,但是它们的协作对象存在差异性,如
何处理?
     将“调用协作对象”这一过程置于Strategy中,Command Pattern的变体


5、如果一个对象集的行为因为属性的取值而存在差异性,如何处理?
     State Pattern



五、中介解耦机制(在解决De-Coupling时,常常使用哪些Indirection的手段)


1)避免重复——只做一次:重复往往代表着耦合,修改一部分重复代码表示要修改其他的

2)DIPDependency 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、Event Style

相比Observer Pattern,可以实现对多个事件的监听。即实现对象间多对多的依赖关系。
其他特点同Observer Pattern

3、Command Pattern

意图:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;请求排
队或记录请求日志,以及支持可撤销的操作。
适用场景:
(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)场景三:一个类不知道它所必须创建的对象的类;一个类希望有他的子类来制定它所创建的对象;类将创建对象这一职责委托给多个帮助子类中的一个,并且希望将哪一个帮助子类作为代理者这一信息局部化
        Factory Method

(4)场景四:控制子类拓展,子类与父类的算法框架相同,但局部实现方法不同
       Template MethodPattern

(5)场景五:多个需创建的类实例之间存在类型依赖关系
       Abstract FactoryMethod

(6)场景六:实例的创建和初始化很复杂,例如运行时刻制定要实例化的类;初始化时变量值发生变更
      Prototype Pattern

原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/192348.html

(0)
上一篇 2021年11月15日
下一篇 2021年11月15日

相关推荐

发表回复

登录后才能评论