当前位置:文档之家› 设计模式及优点总结

设计模式及优点总结

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

什么叫抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义。

实现指的是抽象类和它的派生类用来实现自己的对象。

由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们独自地变化。

这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。

桥接模式的结构图如下:将抽象部分与它的实现部分分离,这不是很好理解,我的理解就是实现系统可能有很多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。

也就是说,在发现我们需要多角度去分类实现对象,而只用继承会造成大量的类增加,不能满足开放—封闭原则时,就应该要考虑桥接模式。

单例模式——Singleton单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象,一个最好的办法就是,让类自身负责保存它的唯一实例。

这个类可以保证没有其他实例可以被创建,并且他可以提供一个访问该实例的方法。

单例模式的结构图如下:单例模式因为Singletion类封装它的唯一实例,这样它可以严格控制客户怎样访问它以及何时访问它。

简单地说就是对唯一实例的受控访问。

当在多线程情景下使用时,需要对GetInstance全局访问点加锁。

适配器模式(Adapter)将一个类的接口转换成客户希望的另外一个接口。

Adapter模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作。

也就是说系统的数据和行为都是正确的但接口不符时,我们应该考虑用适配器模式,目的是使控制范围之外的一个原有对象与某个接口匹配。

适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如说需要对早期代码复用一些功能等应用上很有实际价值。

适配器又两种类型,类适配器模式和对象适配器模式。

但由于类适配器通常是通过多重继承实现的,而C#、、JAVA等语言都不支持多重继承,也就是一个类只有一个父类,所以,我们这里主要讲对象适配器。

适配器模式的结构图如下:Target:这是客户所期待的接口。

目标可以是具体的或抽象的类,也可以是接口。

Adaptee:需要适配的类。

Adapter:通过在内部包装一个Adaptee对象,把源接口转换成目标接口。

2、何时使用适配器模式在使用一个已存在的类时,如果它的接口,也就是它的方法和你的要求不相同时,就应该考虑使用适配器模式。

这样客户端可以调用统一接口就行了,这样客户端代码就可以更简单、更直接、更紧凑。

但是适配器模式也是无奈之举,很有点亡羊补牢的感觉,但是是软件就有维护的一天,所以,通常在软件开发的中后期或维护期在考虑使用它。

这也就是说,一个项目在设计阶段类和方法名就应该要有规范,最好前期就设计好,然后如果在开发阶段发现接口不一致,这时候首先也不应该考虑使用适配器模式,而应该首先考虑去重构统一接口。

只有在双方都不太容易修改的时候再使用适配器模式,而不是一有不同就使用它。

备忘录模式(Memento)在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

这样以后就可将该对象恢复到原先保存的状态。

被网络模式结构图Originator(发起人):负责创建一个备忘录,用以记住当前时刻它的内部状态,并可使用备忘录恢复内部状态。

Originator可根据需要决定Memento存储Originator的那些内部状态。

Memento(备忘录):负责存储Originator对象的内部状态,并可防止Originator以外的其他对象访问备忘录。

备忘录有两个接口,Caretaker 只能看到备忘录的窄接口,他只能将备忘录传递给其他对象。

Originator 能够看到一个宽接口,允许访问返回到先前状态所需的所有数据。

Caretaker(管理者):负责保存好备忘录,不能对备忘录的内容进行操作或检查。

2、何时使用备忘录模式Memento模式比较适合功能比较复杂的,但需要维护或者记录属性历史的类,或者需要保存的属性只是众多属性中的一小部分时,Originator可以根据保存的Memento信息还原到前一状态。

如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销的状态。

状态模式(State)当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。

把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

状态模式的结构图如下:State:抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。

ConcreteState:具体状态,每一个子类实现一个与Context的一个状态相关的行为。

Context:维护一个ConcreteState子类的实例,这个实例定义当前的状态。

2、状态模式的好处与用处将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以,通过定义新的子类可以很容易地增加新的状态和转换。

这样就消除了庞大的条件分支语句。

大的分支语句判断会使得它们难以修改和扩展。

状态模式通过把各种状态转移逻辑分不到State的子类之间,来减少相互间的依赖。

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

组合模式将对象组合成树形结构以表示“部分-整体”的层次结构。

组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式的结构图如下:Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。

声明一个接口用于访问和管理Component的子部件。

Leaf:在组合中表示节点对象,叶节点没有子节点。

Composite:定义有枝节点行为,用来存储子部件,在Component 接口中实现与子部件有关的操作,比如说Add、Remove。

2、组合模式的透明方式和安全方式a) 透明方式:也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。

这样实现Component接口的所有子类都具备了Add和Remove。

这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。

但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以,实现它是没有意义的。

b) 安全方式:也就是说在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子对象的方法,这样做就不会出现刚出现的问题,不过由于不够透明,所以树叶和树枝将具有不同相的接口,客户端的调用要做相应的判断,带来了不便。

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

迭代器模式(Iterator)提供一种方法顺序访问一个聚合对象中各个元素,而不不暴露该对象的内部表示。

当需要访问一个聚焦对象,而且不管这些对象是什么都需要遍历的时候,就应该考虑使用迭代器模式。

特别当需要对聚焦有多种方式遍历时,更应该考虑迭代器模式,为遍历不同的聚焦结构提供如开始、下一个、是否结束、当前哪一个等统一接口。

迭代器模式的结构图如下:Aggregate:聚焦抽象类。

Iterator:迭代器抽象类,用于定义得到开始对象、得到下一个对象、判断是否到结尾、当前对象等抽象方法,统一接口。

ConcreteAggregate:具体聚焦类,继承Aggregate。

ConcreteIterator:具体迭代器类,继承Iterator,实现开始、下一个、是否结尾、当前对象等方法。

2、迭代器的好处迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码同名地访问集合内部的数据。

但是由于它太普遍了,所以各种高级语言都对它进行了封装,所以,反而给人感觉此模式本身不太常用。

组合模式将对象组合成树形结构以表示“部分-整体”的层次结构。

组合模式使得用户对单个对象和组合对象的使用具有一致性。

组合模式的结构图如下:Component为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。

声明一个接口用于访问和管理Component的子部件。

Leaf:在组合中表示节点对象,叶节点没有子节点。

Composite:定义有枝节点行为,用来存储子部件,在Component 接口中实现与子部件有关的操作,比如说Add、Remove。

2、组合模式的透明方式和安全方式a) 透明方式:也就是说在Component中声明所有用来管理子对象的方法,其中包括Add、Remove等。

这样实现Component接口的所有子类都具备了Add和Remove。

这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。

但问题也很明显,因为Leaf类本身不具备Add()、Remove()方法的功能,所以,实现它是没有意义的。

b) 安全方式:也就是说在Component接口中不去声明Add和Remove方法,那么子类的Leaf也就不需要去实现它,而是在Composite声明所有用来管理子对象的方法,这样做就不会出现刚出现的问题,不过由于不够透明,所以树叶和树枝将具有不同相的接口,客户端的调用要做相应的判断,带来了不便。

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

抽象工厂模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

结构图如下:AbstractProductA和AbstractProductB是两个抽象产品,之所以为抽象,是因为它们都有可能有两种不同的实现,如:产品1是用SQL数据库实现的、而产品2是由Access数据库实现的。

AbstractFactory是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。

而ConcreteFactory1和ConcreteFactory2就是具体的工厂了。

由这两个工厂产生具体的产品。

如图中,ConcreteFactory1生产ProductA 1和ProductB 1这两个具体产品。

通常是在运行时刻再创建一个ConcreteFactory类的实例,这个具体的工厂再创建具有特定实现的产品对象,说,为创建不同的产品对象,客户端应该使用不同的具体工厂。

相关主题