大话设计模式观后感之结构型设计模式

大话设计模式观后感之结构型设计模式

六月 02, 2022

外观模式

外观模式(Facade),为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

在原子系统加一层封装,提供系统相关功能完成分层。

在这里插入图片描述

例子

在这里插入图片描述

修改后

在这里插入图片描述

将子系统功能聚合起来

适用场景

  1. 在设计初期阶段,应该要有意识的将不同的两个层分离

  2. 在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,大多数的模式使用时也都会产生很多很小的类,这本是好事,但也给外部调用它们的用户程序带来了使用上的困难,增加外观 Facade可以提供一个简单的接口,减少它们之间的依赖。

  3. 在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,但因为它包含非常重要的功能,新的需求开发必须要依赖于它。此时用外观模式Facade也是非常合适的。你可以为新系统开发一个外观 Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让新系统与Facade对象交互,Facade 与遗留代码交互所有复杂的工作。

信息的隐藏促进了软件的复用

迪米特原则

应该让一个软件中的子系统间的通信和相互依赖关系达到最小,而具体办法就是引入一个外观对象,它为子系统间提供了一个单一而简单的屏障。

适配器模式

适配器模式(Adapter),将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

在这里插入图片描述

在这里插入图片描述

个人理解:这只是一个亡羊补牢的办法,到项目后期时,因为无法修改整个系统,才使用这个方法来统一接口。

例子

在这里插入图片描述

把中文的进攻方法修改成英文。

适用场景

此方法适合用于开发后期,前期更应统一接口,切记。

  1. 使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑用适配器模式。
  2. 两个类所做的事情相同或相似,但是具有不同的接口时要使用它。
  3. 在双方都不太容易修改的时候再使用适配器模式适配。

适配器模式与.NET应用

在.NET 中有一个类库已经实现的、非常重要的适配器,那就是DataAdapter. DataAdapter 用作DataSet和数据源之间的适配器以便检索和保存数据。DataAdapter通过映射FilI(这更改了DataSet中的数据以便与数据源中的数据相匹配)和Update(这更改了数据源中的数据以便与DataSet中的数据相匹配)来提供这一适配器[MSDN]。由于数据源可能是来自SQL Server,可能来自Oracle,也可能来自Access、DB2,这些数据在组织上可能有不同之处,但我们希望得到统一的DataSet(实质是XML 数据),此时用DataAdapter就是非常好的手段,我们不必关注不同数据库的数据细节,就可以灵活的使用数据。

桥接模式

桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立地变化。

常用于项目设计初期。我觉得桥接模式所说的‘将抽象部分与它的实现部分分离,还是不好理解,我的理解就是实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合

解耦这些不同方向的变化,通过对象组合的方式,把两个角色之间的继承关系改为了组合的关系,从而使这两者可以应对各自独立的变化

面对变化,找出变化并封装之

在这里插入图片描述

在这里插入图片描述

例子

在这里插入图片描述

修改后
在这里插入图片描述

适用场景

适用于项目开发前期设计好

组合模式

组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
做一个抽象的类,叶子节点主要是对于本节点的处理,composite更多的是对于之下的节点的管理。

在这里插入图片描述

代码实现

Component

在这里插入图片描述

Leaf

在这里插入图片描述

Composite

在这里插入图片描述
在这里插入图片描述

例子

在这里插入图片描述

透明方式与安全模式

Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。这样实现Component 接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口叫做透明方式。但问题也很明显,因为 Leaf类本身不具备Add(、Remove0方法的功能,所以实现它是没有意义的
Leaf类当中不用Add和Remove方法是安全方式,也就是在Component 接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子类对象的方法,这样做就不会出现刚才提到的问题,不过由于不够透明,所以树叶和树枝类将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。”

使用场景

当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。

好处

组合模式这样就定义了包含人力资源部和财务部这些基本对象和分公司、办事处等组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的地方都可以使用组合对象了。
用户是不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。
组合模式让客户可以一致地使用组合结构和单个对象。任何用到基本对象的地方都可以使用组合对象。

装饰模式

装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
装饰模式顺序很重要。装饰模式是为已有功能动态地添加更多功能的一种方式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

例子

在这里插入图片描述
实现过程有点套娃
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

使用场景

当系统需要新功能的时候,是向旧的类中添加新的代码。这些新加的代码通常装饰了原有类的核心职责或主要行为
在主类中加入了新的字段,新的方法和新的逻辑,从而增加了主类的复杂度,就像你起初的那个‘人’类,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才会执行的特殊行为的需要。而装饰模式却提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包装它所要装饰的对象,因此,当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象了

优点

装饰模式的优点,把类中的装饰功能从类中搬移去除,这样可以简化原有的类
这样做更大的好处就是有效地把类的核心职责和装饰功能区分开了。而且可以去除相关类中重复的装饰逻辑。

享元模式

代理模式

区别

外观模式,适配器模式和桥接模式

外观模式和适配器

都是对现存系统的封装,有人说外观模式其实就是另外一组对象的适配器,这种说法是不准确的,因为外观定义的是一个新的接口,而适配器则是复用一个原有的接口,适配器是使两个已有的接口协同工作,而外观则是为现存系统提供一个更为方便的访问接口。如果硬要说外观模式是适配,那么适配器是用来适配对象的,而外观模式则是用来适配整个子系统的。也就是说,外观模式所针对的对象的粒度更大。

个人理解:外观模式是新建一个类对原有的类进行封装功能,提供统一的接口,而适配器模式是对于原来的类进行继承,对相关类进行重写,并统一接口。

代理模式和外观模式

代理模式和适配器模式