标签 设计模式 下的文章

设计模式:Flyweight

针对问题

当系统中有大量相似对象时,例如一个文本处理程序中的字符,假如用对象来保存每个字符,两个'a'字符对象的字符是相同的,只有位置、颜色、大小等区别,如果为每个字符保存所有信息的话,那么程序占用内存将会十分庞大。Flyweight模式将不同对象直接共享的信息抽取为一个共享对象以节约系统资源。

介绍

运用共享机制有效的支持大量细密度的对象。

实现

Flyweight模式的静态图如下:

其中:
Flyweight类描述了一个操作接口,这个接口接受并作用于外部状态。
ConcerteFlyweight类实现Flyweight接口,并保存内部状态,内部状态是与调用场景无关的,所以它可以在多个调用场景之间被共享。
UnsharedConcreteFlyweight类同样实现Flyweight接口,但它保存的状态并不独立于调用场景,也就是说它可以是非共享的。
FlyweightFactory类管理Flyweight的创建并可以实现引用计数和垃圾回收,这意味着需要屏蔽Flyweight的构造函数。… Read the rest

设计模式:Facade

针对问题

假设多个相互关联的类组成了一个子系统,其他系统在使用这个系统功能的时候必须知道这些类的功能,这无疑加大了使用难度。Facade模式为外部提供了一个统一的调用接口,系统外部想要使用子系统功能时不再需要了解各类型的细节,这类似于面向对象中接口与实现的关系。

介绍

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

实现

Facade模式的实现比较简单,如下图:

Facade需要为客户提供完整的接口,客户在使用子系统时可以不必直接访问子系统中的其他对象。

特点

1、使用Facade模式可以降低子系统的使用难度,并降低系统间的耦合度。
2、调用方如果了解子系统的实现方式也可以跳过Facade,直接使用具体业务对象。

相关文章

设计模式总结

参考文章

  1. 《设计模式_可复用面向对象软件的基础》,
Read the rest

设计模式:Decorator

针对问题

有时我们希望给某个类增加一些功能。这时有两个选择:
1、继承这个类并实现一个派生类,在派生类中编写新的功能逻辑,这样做的主要问题是一个功能就需要对应一个派生类,多层继承时类的数量会成倍增长。
2、使用对象的组合,将新的功能委托给别的对象实现,并提供一致的调用接口。Decorator模式便是这种思路的一个实现方式。

介绍

动态地给一个对象添加一些额外的职责。就扩展功能而言, 它比生成子类方式更为灵活。

实现

Decorator模式的静态图如下:

Decorator模式维护一个单路的层级关系,Decorator与Component需要有共同的接口。可以认为是一个新的Decorator“包裹”了旧的对象,在将调用转发给旧对象后实现Decorator自己的逻辑功能,如下图:

可以看出Decorator模式与Composite模式的实现方式非常相似,这两种模式的主要区别是Decorator模式只需要维护一个component节点,这也体现了这两种模式的区别:Composite模式侧重于对象结构的维护,Decorator模式侧重于转发请求时增加其他功能。… Read the rest

设计模式:Composite

针对问题

一般的GUI框架都会有“容器”和“控件”的概念,一个容器可以包含多个控件,一个容器也可以包含其他容器;控件可以包含子控件,几个控件组合到容器里可以作为新的控件。如果代码实现中单独处理“容器”和“控件”的绘制的话将会十分复杂,如果用递归的方式去思考这个问题,那么问题可以简化成:

这就是Composite模式。

介绍

将对象组合成树形结构以表示“部分-整体”的层次结构。它使得客户对单个对象和复合对象的使用具有一致性。

实现

Composite模式的UML图如下:

Composite是典型的树形结构,如下图:

其中:
1、Leaf节点没有子节点
2、Component节点的Operation被调用时,除了自身的操作(可以空操作),它还会将请求转发给子节点。… Read the rest

设计模式:Proxy

针对问题

假如说我需要对某个类型的调用做一些控制,例如载入一副图片的步骤可以分为三步:

假如说load这一步需要的时间很长,而draw不一定在什么时候调用(比如word文档中的图片要浏览到图片位置时才显示),那么自然会考虑可以在不改变程序结构的前提下把load这一步推迟到draw调用,以节约初始化的时间。这种情况适合于Proxy模式。

介绍

为其他对象提供一种代理以控制对这个对象的访问。
Proxy模式可以分为以下4类:
1、远程代理:为一个对象在不同的地址空间提供局部代表。
2、虚代理:延迟加载大对象。
3、保护代理:控制对原始对象的访问。
4、智能引用:引用计数、单例、锁等。

实现

Proxy模式的静态图如下:

其中:
1、Proxy需要提供与Subject相同的接口。
2、C++中可以重载->操作符以实现对RealSubject的访问,例如:… Read the rest

设计模式:Bridge

针对问题

一个函数通常会包括声明与实现两部分。简单的说,声明的是“做什么”,而实现的内容则是“怎么做”。
在使用继承的面向对象设计中,通过对同一基类的继承,可以让基类中的同一个函数声明在不同派生类中有多个不同的实现。但是,在“派生”一个新类后,这个类所构造实例对象的函数声明和实现在编译时将绑定在一起。也就是说,虽然对于同一个接口,我们可以更换不同的对象来更改它的实现,但是对于同一个对象,它的某个函数的实现方式在编译时就已经确定,运行时无法修改。
Bridge模式则是将声明与实现放在两个不同的对象中,对于同一个对象,它某个函数的实现方式不是唯一的。
而另一个关于继承的问题则是派生类的继承层次问题:因为底层实现代码被绑定在派生类中,如果某个接口下有一个树形的继承关系,那么实现代码将出现在每一个叶子派生类中。如果我们要更换底层实现,那么就要为每一个叶子派生类创建一个平级的替换实现类,这个工作量是庞大的。… Read the rest

设计模式:Adapter

针对问题

适配器(Adapter)的概念在生活中应用相当广泛,比如电器的电源适配器、可以换头的万能螺丝刀等等。将这个概念放在软件开发中:将一个接口转换成我们希望的接口,就是Adapter模式。

介绍

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

实现

类适配器

类适配器使用多重继承对一个接口与另一个接口进行匹配,如图:

对象适配器

对象适配器依赖于对象组合,如下图:

两种方式都实现了将SpecificRequest接口到Request接口的转换。

可插入的适配器

以上两种方式介绍了如何把一个已知类的接口“转换”(适配)成另一个已知类,也就是已知Target和Adaptee,创建Adapter。接下来的问题是:如何把未知类的接口适配到已知类。这里实际上是已知Adaptee,创建Target和Adapter的过程。… Read the rest

设计模式:Prototype

针对问题

一般在需要创建对象时,创建者都是知道需要创建对象的类型之后调用构造函数并用相关的初始化语句完成对象的初始化。假设有这么一个场景:领导拿了一摞演讲稿让你再准备一份,这个时候有两种思路:打开word,把演讲稿重新敲一遍,然后打印出来;或者直接去复印一份。
Prototype模式就类似于复印的思路。这里演讲稿可以作为一个类,稿子里的文字是演讲稿实例中的内容。Prototype模式更准确的说是“利用对象创建对象”的模式,而当作模版的对象就叫做prototype。

介绍

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

实现

基本实现

Prototype模式的UML图如下:

基本实现非常简单,只要让某个类型提供Clone方法,返回自身的拷贝就可以了,但是要注意:
1、为了保证通用性,Clone方法一般是没有参数的。通过复制生成的对象需要在初始化Clone方法外初始化。… Read the rest

设计模式:Builder

针对问题

已知用Factory模式可以方便的创建一类或一组对象。但如果要创建一个由几部分组合而成或需要分布创建的复杂对象,并且复杂对象中包含其他对象的具体类型不确定或创建步骤不确定时,Factory模式就难以适应这种需求了。
一个简单的例子是方便面:泡面一般是开盖-倒水-等3分钟-加料这个顺序下,根据实际泡的东西不同,最终结果可以是泡好的方便面,也可以是方便泡饭,还可以是泡馍。而加料这个步骤可以在倒水前,也可以在倒水后(当然也可以不加)。这就类似于Builder模式的工作原理。

介绍

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

实现

Builder模式分为两个部分:Builder和Director。
Builder:为创建对象各个部件提供相应接口,并提供返回对象的接口。
Director:封装使用Builder构造对象的逻辑。
Builder模式的结构如下图:… Read the rest

设计模式:Singleton

针对问题

系统运行时的某个类仅有一个实例的情况。

介绍

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

实现

单线程

一般Singleton的实现分为3部分。
1、隐藏构造函数
2、创建并保存实例
3、返回实例

例子如下:

分类目录