创建型模式杂谈

[本文首发于cnblogs    作者:byeyear    Email:[email protected]    转载请注明]

本文是关于创建型模式的杂谈,全文的组织结构比较松散,但基本上还是依着原文的编写顺序来谈。

A. 约定

使用”产品“来指代中间产品(如Room、Door、Wall等);

使用”成品“来指代最终的产品(如Maze)。

B. 创建型模式分类

创建型模式可分为两类:类创建型模式和对象创建型模式。

B.1 类创建型模式使用继承改变被实例化的类,例如Factory Method,使用继承改变产品特性;

B.2 对象创建型模式将实例化委托给另一个对象,例如Abstract Factory,将实例化委托给具体的工厂类。

C. MapSite类是产品的公共抽象基类:Enter是这些组件都具有的公共操作。

从直观上(现实角度)来看,Room、Door、Wall这些产品似乎难以有一个公共的基类。可以这样考虑:首先,Room、Door、Wall这三种产品作为Maze的构成要素,应该是平行的;其次,考虑这三种产品有什么样的公共属性,并将其提取出来作为基类。

D. Room一方面继承于MapSite,另一方面又包含四面MapSite指针:同时运用了继承和组合。

E. Maze类是Maze的表示,MazeGame类负责Maze的创建——将Maze的表示和创建分离开来。这有利于将来单独改变Maze的表示或Maze的创建。比如,Maze可以用链表表示,也可以用数组表示,改变其表示方式不会影响到MazeGame类。

F. 原文中所说的”对布局进行硬编码“有两个方面的意思:一是对迷宫结构的硬编码,二是对迷宫构件的硬编码。前者使得增删房间等操作变得困难,后者使得难以采用不同特色的构件如BomedRoom。Builder模式是解决前者的,其他模式都用于解决后者。

G. AbstractFactory

G.1 Client仅适用Abstract Factory提供的接口创建对象,而不使用特定的具体类的接口;实际的对象创建由(继承于Abstract Factory的)Concrete Factory完成。由于各Concrete Factory具有(继承于Abstract Factory的)完全相同的Product生产接口,所以各个Concrete Factory的产品线必须完全一致。这样,如果Abstract Factory需要增加新的产品接口,所有Concrete Factory都必须修改。Abstract Factory模式使得各Product之间强相关。假如你有两个Factory甲和乙,生产三种Product A、B、C,Client要么使用甲A甲B甲C,要么使用乙A乙B乙C,而不能同时使用甲A和乙B。这既是优势也是缺点:这种特性有利于产品的一致性,非常适合于一个系列的产品对象必须一起工作的情况;但对于不同Factory的产品对象要能够互换的情况显然不合适。

G.2 典型的Abstract Factory的例子是支持多种视觉风格的用户界面工具包:界面上的各widget风格必须统一,因此不可能在同一界面上使用多个Widget Factory(不同Concrete Factory的产品不可互换);不同风格的界面总是有相同种类的Widget(不同的Concreate Factory具有相同的产品线)。

G.3 在Abstract Factory中定义产品接口并在Concrete Factory中实现的做法实际上就是Factory Method:将产品的创建延迟到具体的Concrete Factory中。

G.4 原始代码与采用了Abstract Factory模式的代码对比:

原始版本:

Maze* MazeGame::CreateMaze()

{

Maze *aMaze = new Maze();

Room *r1 = new Room(1);

}

修改版本:

Maze* MazeGame::CreateMaze(Factory& factory)

{

Maze *aMaze = factory.MakeMaze();

Room *r1 = factory.MakeRoom(1);

}

和原始版本相比,修改版本不直接生产Product,而是在代码某处new一个Factory出来,由这个Factory生产。

H. Abstract Factory和Factory Method的对比

H.1 Abstract Factory:一般来说,Abstract和Concrete Factory都在“框架”中实现。Client直接使用框架设计者提供的Concrete Factory来创建Product,一般不会去创建新的Factory(Client仅使用Product,而不生产Product)。这是因为Abstract Factory的每次改动都会涉及Concrete Factory,Abstract类和Concrete类是“联动”的,它们不适合分开在不同的设计者层次中实现。

H.2 Factory Method:框架设计者提供Interface,由Client实现之(Client需要自己生产Product)。

H.3 Abstract Factory中,产品系列总是整体替换;

H.4 Factory Method更适合于对已有产品特性进行修正、更改、扩充。

H.5 Abstract Factory中产品和工厂强关联。

H.6 Factory Method中产品和Creator关联不强。比如基类的Creator使用产品X、Y、Z,继承类可以使用产品X+、Y+、Z,而X+、Y+分别继承于X、Y。

H.7 Factory Method用于生产过程中部分产品或产品部分特性的修改,或生产过程中某个步骤的具体实现的修改(但步骤或流程本身不变)。

I. Builder Mode

I.1 Builder模式主要讲的是如何build,和其他三种模式的关注点不一样。

I.2 将对象的构建和表示分离,使得同样的构建过程可以创建不同的表示。

I.3 以RTF转换器为例子,对同一篇文档,构建过程是一样的(ParseRTF),但使用不同的Converter可以得到不同的表示:相同的构建过程,不同的构建结果。

I.4 所有的Builder必须具有相同的抽象借口,这样不同的Builder之间才能互相替换。

I.5 Director负责下达指令,Builder负责执行指令;一个是领导,一个是员工;Director有图纸,Builder负责造。

I.6 框架提供各种Builder,Client创建Director对象,并用所需的builder配置它。

I.7 Builder Mode隐藏了产品内部结构。

J. Abstract Factory和Builder模式的联合应用

Director是设计院,Builder是施工队,Factory是材料商。Director的七姑的八姨的小舅子是材料商的女儿的同学的妈妈的孩子:

// Director告诉Builder必须使用指定factory提供的材料

void StandardBuilder::BuildRoom(Factory& factory, int n)

{

Room *room = factory.CreateRoom();

......

}

K. Builder模式和Abstract Factory模式

K.1 Abstract Factory着重产品系列整体替换;

K.2 Builder模式着重构建过程。

L. Factory Method模式

L.1 以App/Doc框架为例子, App在用户从菜单中选择New时创建Doc。

App知道Doc何时创建,但不知道哪一种Doc子类被创建。

-> 应用场景:知道某个子类何时创建,但暂时还没有该子类的实现。

App/Doc框架不知道具体子类,因此Doc子类对象的创建只能在App子类而不是App父类里做,因此App父类需要一个virtual的CreateDocument函数并由App子对象在其中new一个Doc子对象(App子类是知道Doc子类的)。

父类(框架)负责过程(CreateDoc,docs.Add,doc->Open),这个过程对不同的App/Doc是一致的;子类负责过程中需要用到子类的那些步骤的具体实现。

跳出App/Doc框架来看,Factory Method的基类定好产品工序,子类根据需要修改/实现某一道或某几道工序。改变产品类就必须创建新的子类。

L.2 迷宫游戏原始版本:

Maze* MazeGame::CreateMaze()

{

Maze *aMaze = new Maze();

Room *r1 = new Room(1);

}

L.3 修改版本:

Maze* MazeGame::CreateMaze()

{

Maze *aMaze = MakeMaze(); // Virtual function

Room *r1 = MakeRoom(1); // Virtual function

}

M. 类平行层次

一个类将它的一些职责委托给一个独立的类。被委托的职责仅在较少的时候需要,因此不需要被保存在委托方。

N. ProtoType模式

----------------------------------- 分割线 ----------------------------------

原文的下面这句话似乎翻译有问题:

……为定义选择板中的那些工具,还提供一个抽象类Tool。该框架还为一些创建图形对象实例并将它们加入到文档中的工具预定义了一个GraphicTool子类……

这句话的意思应该是这样:

……为定义选择板中的那些工具,还提供一个抽象类Tool。例如,该框架为创建图形对象并将它们加入到文档的工具预定义了一个GraphicTool子类。类似的还有旋转图形对象的RotateTool子类。

----------------------------------- 分割线 ----------------------------------

N.1 GraphicTool用来对Graphic进行操纵,这样初想起来Manipulate类似乎可以作为Graphic的一个成员。然而这种想法并不好;理由:

1) Manipulate类不是Graphic类自身所具有的某种“属性”或“方法”,而是外部强加上去的;相比较而言,Draw操作就是Graphic类自身应该具有的。

2) 不同Graphic的同种Manipulate是类似的:比如GraphicTool创建并绘制一个新的Graphic;RotateTool旋转一个Graphic。

3) 施加于Graphic的Manipulate是不可预测的。现在有了GraphicTool和RotateTool,将来可能会有ScaleTool和FlipTool。

以上,一句话概括,解耦了Graphic类和Tool类。

N.2 Graphic需要动态创建,适合于ProtoType。

N.3 为什么需要clone而不是new

因为我们无法预先知道需要创建的对象类型,因此无法new(对于Smalltalk这不是问题;因此这种模式在Smalltalk中用处不大)。用音乐编辑器做例子,用户想要什么样的Graphic,你就要clone什么样的Graphic。框架设计者不可能知道client会鼓捣出什么样的Graphic,于是要求client必须为他们的Graphic提供clone操作供GraphicTool类使用。

O. 几种创建型模式对比

O.1 Abstract Factory

A厂家生产A-Wall,A-Room,A-Door

B厂家生产B-Wall,B-Room,B-Door

C厂家生产C-Wall,C-Room,C-Door

各家产品能够各自配套;建造Maze时可以全用A家的三款产品,也可以全用B家的或全用C家的,但三家产品不能混用。框架设计者已帮你做好三个厂家和他们的所有产品,Client直接用就是了。

不同厂家的同种材料之间是并列关系。

O.2 Factory Method

已经有了基本的砖头Wall、木质Room和拼木的Door,通过继承使用刷了漆的Wall、装修过的Room以及实木的Door。Wall、Room和Door这三款产品可以仅替换其中一个。框架设计者只提供基本的Wall、Room和Door,更精美的Wall、Room和Door由Client通过继承实现。框架设计者还提供了Maze的构建过程。Client一般不修改构建过程,只通过继承Maze并在Derived Maze中使用自己的材料来替换标准材料。

同种材料之间存在继承关系;不存在直接的并列关系。

O.3 PROTOTYPE

有的Client想要A-Wall,B-Door,C-Room;

有的Client想要A-Wall,D-Door,E-Room……

如果是Factory Method,每种组合都需要一个MazeGame子类;使用ProtoType,只要用不同的对象构造MazeFactory。

[本文首发于cnblogs    作者:byeyear    Email:[email protected]    转载请注明]

时间: 2024-10-01 04:52:11

创建型模式杂谈的相关文章

设计模式---创建型模式

一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. (3)行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 二.设计模式的六大原则 1.开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修

java设计模式--创建型模式

2016-04-24 10:10:34 创建型模式:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 注意:工厂模式可以分为三类: 1)简单工厂模式(Simple Factory) 2)工厂方法模式(Factory Method) 3)抽象工厂模式(Abstract Factory)  这三种模式从上到下逐步抽象,并且更具一般性.GOF在<设计模式>一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory).将简单工厂模式

C#面向对象设计模式纵横谈——2.Singleton 单件(创建型模式)

一:模式分类 从目的来看: 创建型(Creational)模式:负责对象创建. 结构型(Structural)模式:处理类与对象间的组合. 行为型(Behavioral)模式:类与对象交互中的职责分配. 从范围来看: 类模式处理类与子类的静态关系. 对象模式处理对象间的动态关系. 二:Singleton (创建型模式) 单件 1.动机(Motivation) 软件系统中,经常有这样一些特殊的类,必须保证他们在系统中只存在一个实例,才能确保它们的逻辑正确性,以及良好的效率. 如何绕过常规的构造器,

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

创建型模式1.2简单工厂模式

一.概念 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例.从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 二.类图 三.具体介绍 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例. 该模式中包含的角色及其职责 工厂(OpertionFactory)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂

设计模式之创建型模式(上)

没有总结的学习不算学习,这一个月的学习可谓收获多多啊,接下来与大家分享一下. 一.设计模式的分类 总体来说设计模式分为三大类: 1.创建型模式,共五种. 2.结构型模式,共七种. 3.行为型模式,共十一种. 首先研究创建型模式 二. 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统独 立于如何创建.组合和表示它的那些对象. 三. 为什么需要创建型模式 所有的创建型模式都有两个永恒的主旋律: 第一,它们都将系统使用哪些具体类的信息封装起来: 第二,它们隐藏了这些类的实例

设计模式——创建型模式

简单的说我们可以把23种设计模式可以归为三大类,分别是创建型模式.结构型模式和行为型模式. 今天,首先看一下创建型模式.创建型设计模式包括5种:单例模式(Singleton).工厂方法模式(Factory Method).抽象工厂模式(Abstract Factory).建造者模式(Builder).原型模式(Prototype).  1.单例模式(Singleton)        1)简介 保证一个类仅有一个实例,并提供一个访问它的全局访问点. 单例模式是一种常用的软件设计模式.在它的核心结

设计模式(三) : 创建型模式--工厂方法模式

工厂方法模式区别与简单工厂模式主要在于,factory中对对象的实例化延迟到了子类的factory中, 这也是优于简单工厂的地方.下面看这个模式的类图(截自<java与模式>): 示意性代码: ? 1 2 3 4 5 6 7 package com.javadesignpattern.factorymethod; public interface Creator {          public Product fatcory(); } package com.javadesignpatte

Java的23种设计模式详解整理之创建型模式

最近重新阅读"四巨头"的设计模式. 对一些设计模式有了更多的理解. 原著中的例子是C++写的,不好理解. 这里我换成了Java, 代码示例仅供参考,没有具体实现. 介于个人水平有限,如有纰漏,请指正.有问题的朋友可以私信我或者发我邮箱(请到我主页查看),我看到就会回复. 希望和大家一起进步. 工作中有时候最困难的不是怎么去实现一个功能,而是怎么去设计一个功能.我常常会因为频繁改动需求大费脑筋.之后我在思考如何将一个功能在设计之初就做好扩展的准备,防止需求变动导致大面积的修改.code之