再读GOF设计模式-创建型模式

上次读设计模式的书还是5年前上学那会,选择的是《大话设计模式》这种比较通俗易懂的书。虽然说当时看完觉得挺明白的,但是随着工作年限的增长发现自己并没有把学过设计模式真正主动的应用在项目里。我认为这主要是因为上学时候没有项目经验算是纸上谈兵,而真的工作时又没有投入精力关注到模式的应用,所以读过的理论也仅仅是理论。

我感觉设计模式这个东西,在你最初编程基础技能薄弱的时候是很难去体会到它的重要意义的,这个阶段往往更多的精力投入在系统api,第三方库,各种开发实用技能,甚至关注架构,分布式这些更加高层的领域,知识广度不断的增长。

到了编程中期,会逐渐认识到开发实用技能虽然重要,但是由于没有好的设计模式作为范本的原因,这些年做的很多开发实际上是在闭门造车或者说只是掌握了一些解决特定领域的模式,并且有可能养成了很多坏的设计习惯,如果不重学设计模式,很难把坏的品位纠正回来的,我们知道坏习惯总是很难纠正,在软件设计里也是一样的。

从这篇博客开始,我将重读GOF设计模式这本书,但是我并不会像网上各种设计模式的书那样把书中的内容再复述一遍,我更加关注模式间的差异,我认为只有比较同类的设计模式之间的差异,才能更加明白为何出现那么多设计模式以及何时应该使用何种模式。

创建型模式

这一类模式是用来创建对象的,本质都是为了避免分配类对象这个事情散落到各种业务代码里,这样如果要替换对象类型就要改很多调用方代码。

既然要抽象分配对象这个事情,首先对象必须是抽象的,否则调用方代码不可能通用,这个很容易理解。

其次,分配对象难免要new一个具体的类型,所以只要把这个new具体对象的过程藏起来,那么调用方就不用随着对象类型的改变而受影响了,这也不难理解。在隐藏具体对象是什么的这个事情上,有朴素的做法也有灵活的做法,有细粒度的做法也有粗粒度的做法,下面就讲一下几种模式的差异。

简单工厂方法:构造1种产品,通过参数控制返回不同类型的对象。

比如奥迪生成汽车产品,那么有奥迪轿车,奥迪跑车,它们都是车,我是来买车的,我要奥迪轿车就给我奥迪轿车,我要奥迪跑车就给我奥迪跑车,那么这个方法就是简单工厂方法。可以看出来,我只需要调用这个方法并传参说明要轿车还是跑车,它就返回不同的汽车给我。

工厂方法:构造1种产品,继承接口实现多个工厂方法

简单工厂是一个工厂方法通过参数控制返回不同对象,如果不想参数来控制分配不同对象,那么可以为每个类型实现一个工厂方法,这就需要提取一个抽象基类,不同的类型继承基类,实现工厂方法返回不同类型的对象。

这里产品是汽车,然后奥迪轿车和奥迪跑车是2种不同类型的汽车,为了摒弃参数控制的形式,我们做一个抽象类提供一个抽象的create方法,然后继承一个奥迪轿车工厂并让其create方法返回奥迪轿车,继承一个奥迪跑车工厂让它其create方法返回奥迪跑车。

如果调用者要生产汽车,我们可以在外部提前决策好选择奥迪轿车工厂还是奥迪跑车工厂,将工厂传给调用者,这样调用者就可以简单的调用create拿到自己的汽车了。

抽象工厂:构造N种产品,继承接口实现多个工厂

抽象工厂和工厂方法很容易搞不清区别,请先关注红色字体部分的叫法差异:工厂方法主体是方法,抽象工厂主体是工厂,前者抽象的是方法,后者抽象的是工厂。

工厂方法用来构造1种产品,比如汽车;一个工厂用N个工厂方法生成N种产品,比如汽车和飞机;这是2个模式的核心差异。

奥迪可以生产汽车和飞机这2种产品,汽车可以是奥迪轿车和奥迪跑车,飞机可是是奥迪客机和奥迪战斗机,那么奥迪的Boss可能想建一个能生产奥迪轿车和奥迪战斗机的工厂,以及一个生产奥迪跑车和奥迪客机的工厂,其实就需要把工厂抽象,这个抽象工厂有2个抽象方法,一个是create汽车,一个是create飞机,2个工厂都继承抽象工厂,然后实现2个create方法既可。

这样的话,我们在外部决策选择轿车+战斗机的工厂还是跑车+客机的工厂,将工厂其传给调用者,调用者只需要依赖抽象工厂,之后调用者按需create汽车或者create飞机,至于汽车和飞机来自哪个工厂以及是哪种汽车和哪种飞机,对调用者来说都是透明的。

不过抽象工厂缺点明显,如果增加一个新的产品到抽象基类,那么所有继承它的工厂都要添加生产新产品的方法实现。

构造者模式:构造1种产品,调用者可以掌控产品的组成部分,最后取得订制的完整产品。

这个模式和工厂方法很像,都是继承接口创建同1种商品不同类型的对象,但是构造者模式并不是简单的create就返回对象了。对于一量奥迪的轿车来说,有方向盘有轮子有发动机有导航仪有蓝牙,那么有的买家不想要蓝牙,有的买家不想要导航仪,是不是可以订制呢?构造者模式不仅要提供create工厂方法,还要提供一些构造组件的方法,比如安装蓝牙,安装导航仪,调用者可以按自己意愿按需调用对应的方法,最后调用create可以得到一个订制化的奥迪轿车。

也就是说,构造者模式强调的是产品的组成可以订制,每个组成部分是抽象的和可变的,同时也支持工厂方法的抽象,从而可以生产不同配置的奥迪轿车,奥迪跑车,但前提是他们必须是同一种商品:汽车。

原型模式:构造1种产品,从现有产品对象拷贝一份,新对象内容可以有调整。

这个模式适用于一些场景,奥迪轿车可以克隆一个奥迪轿车,奥迪跑车可以克隆一个奥迪跑车,这对于调用者来说不需要关心具体是什么车,因为克隆方法是抽象的。

单例模式:构造1种产品,但全局只有1个对象。

这个无需说明。

下一篇将学习 结构性模式

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~