GoF23种设计模式

GoF23种设计模式(第一遍读)  

  最近在看一本书,一位大叔给我推荐的《GoF23种设计模式》。以前有听过设计模式这个词,但没有去仔细了解过。只是自己有一个模糊的认识。现在把这本书先过一遍,粗略的记一下笔记。书读三遍,其义自见。这是我的第一遍。   

  • 面向对象系统的分析和设计实际上追求的就是两点:高内聚(Cohension)和低耦合(Coupling)
  • 设计模式是一种思想,其实我们平常开发过程中,已经应用了一些设计模式,不过不知道,哦原来这就是××模式
  • Observer其实例是(Model-View-Control),也就是被说烂了的MVC模式。MVC好像有很多实例。什么Spring MVC之类的。

创建型模式

1.1 Factory模式
问题1:为了提高内聚和低耦合,我们会抽出一些类的公共接口以形成抽象类或者接口。这时候,通过声明一个指向基类的指针来指向实际的子类实现,达到多态的目的。但是当我们要使用一个子类的时候,必须知道子类的名称。然后继承自一个抽象类的子类何其多。子类的名字很难记。程序的扩展性和维护变得越来越困难。
问题2:在父类中不清楚要具体实例化哪一个具体的子类。比如类A中要用到抽象父类B,但是A并不清楚具体要实例化哪一个B的子类。但是在类A的子类D中是可以知道的。所以A中基本上写不出来 new XXX,因为它根本不知道要XXX是什么。

这两个问题也就引出了Factory模式的两个最终呀的功能:

  1. 定义了创建对象的接口,封装了创建对象的过程
  2. 使得具体化类的工作延迟到了子类中(具体做法就是提供一个创建子类的接口,并且在子类中提供具体实现,因为在子类中可以决定到底实例化哪一个类)

总结
  Factory模式对于对象的创建,给予开发人员提供了很好的实现策略,但是Factory模式仅仅局限于同一个基类,如果我们要为不同类的类提供一个对象创建的接口,那就要用AbstractFactory了。
  
1.2 AbstractFactory模式
问题:比如我现在要做一款游戏,里面有各种级别的怪物,初级,中级,高级怪物。而他们都继承自怪物这个类。那也就是说在这个系统中,成千上万的怪物实例都要基于怪物这个类,而保证不会出错。

AbstractFactory模式是用来解决这类问题的:要创建一组相关或相互依赖的对象。
而AbstractFactory模式的关键就是将这一组对象的创建封装到一个用于创建对象的类(ConcreteFactory)中,维护这样一个创建类总比维护n多相关对象的创建过程要简单的多。

注意:初学者容易混淆AbstractoryFacroty模式和Factory模式。实际上,AbstractoryFacroty模式是为了创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式是为了一类对象提供创建接口,或延迟对象的创建到子类的实现。并且经常可以看到AbstractoryFacroty模式通常是使用Facroty模式实现。

1.3 Singleton模式
问题: Singleton模式要解决的问题是: 我们怎样去创建一个唯一的变量(对象)? 在基于对象的设计中我们可以通过创建一个全局变量来实现。但是在纯粹的面向对象范式中,可能就只能通过Singleton模式来实现了。

Singleton模式是通过维护一个static的成员变量来记录这个唯一的对象的实例。通过提供一个static的接口instance来获得这个唯一的实例。

补充说明: Singleton模式的实现无须补充解释,需要说明的是,Singleton不可以被实例化,因此我们将其构造函数声明为protected或者直接为private

1.4 Builder模式
  当我们要创建的对象很复杂的时候(通常是由其它的对象组合而成),我们要将复杂对象的创建过程和这个对象的表示分离开,这样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。
  讨论
  Builder模式是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(通过传入不同的参数)。
  Builder模式和AbstractFactory模式在功能上很相似,都是用来创建复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果。一般来说Builder模式中对象不是直接返回的。而在AbstractoryFactory模式强调的是为多个相互依赖的对象提供一个统一的接口。
  
1.5 Prototype模式
Prototype模式提供了一种自我复制的功能,就是说新对象的创建可以通过已有对象进行创建。这个模式提供了一个通过已存在对象进行新对象创建的接口(clone)
讨论
Prototype模式通过复制原型(Prototype)而获得新对象创建的功能,这里的Prototype本身就是“对象工厂”(因为能够生产对象),实际上Prototype模式和Builder模式、AbstractFactory模式重在产生多个相互依赖类的对象,而Prototype模式重在自身复制自己创建新类。

##结构型模式
2.1 Bridge模式
这个Brige模式,表示看不太懂,感觉蛮复杂的。先引述书中的一段描述吧,以后有了理解,再添加进来。

使用组合(委托)的方式将抽象和实现彻底解耦,这样的好处是抽象和实现分别可以独立变化。

2.2 Adapter模式

问题:我们为了完成某项工作购买了一个第三方的库来加快开发。这就带来了一个问题我们在应用程序中的设计好的接口,与第三方提供的接口不一致。为了使这些不兼容的类可以在一起工作,Adapter模式提供了一个类(第三方库接口)转化为客户希望的接口。
上面的解决方式也刚好对应了Adapter模式的两种类别:类模式和对象模式。
在Adapter模式的结构图中可以看到,类模式的Adapter采用继承的方式服用Adaptee的接口,而在对象模式的Adapter中我们则采用组合的方式实现Adaptee复用。

Alt text

讨论
在Adapter模式的两种模式中,有一个很重要的概念就是接口继承和实现继承的区别和联系。接口继承和实现继承是面向对象领域的两个重要的概念,接口继承指的是通过继承子类获得了父类的接口,而实现继承指的是通过继承子类获得了父类的实现(并不统共接口)。

2.3 Decorator模式

问题: 在OO设计和开发过程,可能会经常遇到以下的情况:我们需要为一个已经定义好的类 添加新的职责(操作),通常的情况我们会给定义一个新类继承自定义好的类,这样会带来一个问题(将在本模式的讨论中给出)。通过继承的方式解决这样的情况还带来了系统的复杂性,因为继承的深度会变得很深。

Alt text

Decorator提供了一种给类增加职责的方法,不是通过继承实现的,而是通过组合。在OO设计和分析经常有这样一种情况:为了多态,通过父类指针指向其具体子类,但是这就带来另外一个问题,当具体子类要添加新的职责,就必须向其父类添加一个这个职责的抽象接口,否则是通过父类指针是调用不到这个方法了。这样处于高层的父类就承载了太多的特征(方法),并且继承自这个父类的所有子类都不可避免继承了父类的这些接口,但是可能这并不是这个具体子类所需要的。而在Decorator模式提供了一种较好的解决方法,当需要添加一个操作的时候就可以通过Decorator模式来解决,你可以一步步添加新的职责。

2.4 Composite模式

问题:在开发中,我们经常可能要递归构建树状的组合结构,Composite模式则提供了很好的 解决方案。

Alt text

Composite模式和Decorator模式有着类似的结构图,但是Composite模式旨在构造类,而Decorator模式重在不生成子类即可给对象添加职责。Decorator模式重在修饰,而Composite模式重在表示。

2.5 Flyweight
问题:在面向对象系统的设计何实现中,创建对象是最为常见的操作。这里面就有一个问题: 如果一个应用程序使用了太多的对象,就会造成很大的存储开销。特别是对于大量轻量级(细粒度)的对象。比如在文档编辑器的设计过程中,我们如果为没有字母创建一个对象的话,系统可能会因为大量的对象而造成存储开销的浪费。例如一个字母“a”在文档中出现了100000次,而实际上我们可以让这一万个字母“a”共享一个对象,当然因为在不同的位置可能字母“a”有不同的显示效果(例如字体和大小等设置不同),在这种情况我们可以为将对象的状态分为“外部状态”和“内部状态”,将可以被共享(不会变化)的状态作为内部状态存储在对象中,而外部对象(例如上面提到的字体、大小等)我们可以在适当的时候将外部对象最为参数传递给对象(例如在显示的时候,将字体、大小等信息传递给对象)。

可以从图中看出,Flyweight模式中有一个类似Factory模式的对象构造工厂 FlyweightFactory,当客户程序员(Client)需要一个对象时候就会向FlyweightFactory发出请求对象的消息GetFlyweight()消息,FlyweightFactory拥有一个管理、存储对象的“仓库”(或者叫对象池,vector实现),GetFlyweight()消息会遍历对象池中的对象,如果已经存在则直接返回给Client,否则创建一个新的对象返回给Client。当然可能也有不想被共享的对象(例如结构图中的UnshareConcreteFlyweight

  今天不妨先到这儿,后面的东西在慢慢看,觉得理解了,或者有必要的话再加入进来。说实话,今天写这个设计模式的东西,也就大概了解了前面四五中是什么情况,不过后面写这些其它的模式的时候,有特么忘了。以后再看吧。
感觉严格地讲,写特么这么多(主要是copy),算不算是博客啊?好像有点过于长。不过管他呢,微博不是创新了一下,140个字,就火了。爱长长,爱短短。

赏口饭吃,哈哈!