2012年9月25日星期二

创建型模式总结

创建型模式总结

前言

到今天为止,我们已经把GOF设计模式中的创建型模式都介绍完毕呢,总结起来就是:工厂方法模式、抽象工厂模式、生成器模式、原型模式及单例模式。通过前面的介绍,希望能让大家对创建型模式有一个新的认识和理解,讲解有什么不恰当的地方还希望大家提出来,一起交流和进步。总之一句话,之所以要写该系列文章,除了加深自己对23种设计模式的认识和理解外,也是将把自己对其的”掌握“诉诸博客,希望能得到各位的认同和指点,在设计的道路上一同进步!自己也会坚持把剩下的结构型模式和行为型模式都介绍完,完成自己当初的承诺和愿景吧!

概述

创建型模式,顾名思义就是创建对象的模式,对对象实例化过程进行了抽象(这根本就是废话嘛)。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。这些模式之间不断出现着两个主旋律,一是它们都将关于该系统使用哪些具体的类的信息封装起来;二是它们隐藏了这些类的实例是被如何创建和放在一起的。整个系统关于这些对象知道的只是其抽象类所定义的接口接口。这样,创建型模式在何时(when)被创建,谁创建(who)创建以及如何创建(how)方面给予我们设计上的很大灵活性。

创建型模式缘由

在没有引进创建型模式时候,在需要对应的类对象时,我们通常会直接通过new的方式来创建对象实例,在这里,我们虚拟一个游戏开发场景来说明(说明:这个场景很多博客都有引用,若有雷同,还请见谅!)。

当我们需要一个现代风格样式wall时,按照大众的想法,通过直接进行创建:

1:  Wall wall=new ModernWall();

就这样我们获得了具有现代风格模式的wall,此时由于游戏场景的变化,我们又需要古典风格样式的wall,按照上述做法,很简单,同样的创建手法:

1:  Wall wall=new ClassicalWall(); 

这样的创建方式乍看一下似乎没有什么太大问题,但是大家是否想过,在一个实际的系统中,这样创建逻辑通常遍布系统的各个地方,如果在某一时刻只是因为wall风格的改变,就需要修改系统中所有这样的创建语句,如此一来,造成的修改工作量将是很大的,而且也极易出错。接下来,我们通过工厂方法来封装对象的创建逻辑,将对象的创建置于一个工厂方法中,再来看看实现的效果:

1:  Factory factory=new ModernFactory();
2:  Wall wall=factory.Create();

如果此时,需要将现代风格的wall对象实例改变成古典风格的wall,我们可以这样做:

1:  Factory factory=new ClaasicalFactory();
2:  Wall wall=factory.Create();

可以看到,当需要不同风格的wall时,由于Wall类是所有风格wall的抽象公共接口,我们只需要创建对应风格的工厂对象,由其完成对应的对象创建工作,而具体的创建代码不需要改变,也是Wall wall=factory.Create()不需要改变。在这里,大家可能会有一个疑问,这样的一种方式,不也得每次创建新的工厂对象吗?注意, 这里说的工厂对象一般的指的是”全局性的对象“,换句话来说,就是系统中所有wall的创建都由这个工厂对象来完成,这样一来,当我们需要不同风格的wall对象时,只需改变这个对应工厂对象即可。借用idior的话来说创建型模式的作用主要就是以下两点:

  1. 封装逻辑变化,绝不仅仅是new一个对象那么简单。
  2. 封装创建逻辑,客户代码尽量不修改,或者小修改。

这或许就是创建型模式被前人总结出来的“缘由”吧!

五种创建型模式一览

  1. 工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类,也就是将创建工作推迟到子类来完成。换句话来说就是,工厂类本身是一抽象类,实际的对象创建工作由其子类来完成,工厂类本身只是完成了对对象创建工作接口的定义而已。
  2. 抽象工厂模式:提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们(指的是这些相关或者相互依赖的对象)的具体的类。换句话来说,就是抽象工厂只定义好创建这些不同实现的对象的接口,这样客户可以在不指定具体产品类型的情况下,创建同属于一个产品族的多个产品对象,强调的是“相关的系列对象”的创建问题。
  3. 生成器模式:将一个复杂对象的构建和它的表示相分离,使得同样的构建过程可以创建出不同的表示。换句话来说就是,生成器模式把对象的构建逻辑转移到了类的外部,在类的外部来定义构建逻辑,这样做的好处便是可以将一个复杂对象的构造过程与其表示相分离,也将一个复杂对象的构建分成若干个子部件的构建问题强调的是对象的构建过程。
  4. 原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。换句话来说就是,隐藏了对象的创建过程,而且还是通过拷贝原型实例来创建新的对象,这个新对象与原型类型一致,但是内部属性可以不一致。在实际的系统开发中,我们通过会定义一个原型注册器来管理所有的原型实例。
  5. 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。换句话来说就是,单例模式通过将单例类的构造器访问修饰符设置为private,禁止客户直接通过new的方式来实例化单例类;与此同时,单例类提供一个静态访问点来获取到通过内部创建出的唯一单例类对象。很明显,单例模式解决的是实例对象的个数问题,而其他的四种创建型模式都是用来解决直接通过new的方式来创建实例对象的带来紧耦合关系。

创建型模式的选择

面对上述五种创建型模式,在实际的开发过程中,我们将如何选择最适合的模式呢?当然,影响因素有很多,这需要我们学会去权衡各个创建型模式的利弊,自然在权衡之前,我们首先需要对各个创建型模式形成自己较深刻的见解,这样在面临抉择的时候才能根据实际需求作出最恰当的选择。通常来说,抽象工厂模式、生成器模式、原型模式都较工厂方法模式实现起来更加复杂一些,但是使用也更加灵活一些。但是越复杂、越灵活的东西实现起来自然也就越复杂,比如抽象工厂模式,在实现的过程中可能需要较多的工厂类来支撑,因为对于产品族中的各个具体产品都需要一个对应的工厂类来创建。通常,在软件设计之初,我们会从工厂方法模式开始设计,只有当系统中需要更大的灵活性或者说工厂方法已经不能很好地满足我们的设计理念的时候,此时,作为系统设计师的我们,便需要将设计向其他的创建型模式进行推进和演化,这当然也需要你对所有的创建型有一定的了解,这样才能在权衡各种设计模式时显得游刃有余。

至于对创建型的各个模式的详细代码演绎,在这里就不再举例列出呢。这里推荐大家去看看TerryLee对创建型模式专题总结的文章还有就是idior对创建型模式详解的文章,个人觉得讲得都比较棒,相信大家看后亦会有同感!

结束语

理解和掌握了各种创建型模式,也就向优雅的对象创建境界更迈近了一步。请记住,创建型模式主要是为了提高代码的可维护性和可扩展性,让系统独立于对其所需对象的创建、组合和表示问题!对创建型模式总结就到这呢,详细的介绍希望大家参考前面对各个创建型模式的介绍文章,接下来,我们将继续介绍学习结构型设计模式,敬请期待!

参考资料

  1. 程杰著《大话设计模式》一书
  2. 陈臣等著《研磨设计模式》一书
  3. GOF著《设计模式》一书
  4. Terrylee .Net设计模式系列文章
  5. 吕震宇老师 设计模式系列文章

TAG: