概述

创建型模式,就是用来创建对象的模式,抽象了实例化的过程。它帮助一个系统独立于如何创建、组合和表示它的那些对象。本文对五种常用创建型模式进行了比较,通过一个游戏开发场景的例子来说该如何使用创建型模式。

为什么需要创建型模式

所有的创建型模式都有两个永恒的主旋律:第一,它们都将系统使用哪些具体类的信息封装起来;第二,它们隐藏了这些类的实例是如何被创建和组织的。外界对于这些对象只知道它们共同的接口,而不清楚其具体的实现细节。正因如此,创建型模式在创建什么(what),由谁(who)来创建,以及何时(when)创建这些方面,都为软件设计者提供了尽可能大的灵活性。

假定在一个游戏开发场景中,会用到一个现代风格房屋的对象,按照我们的一般想法,既然需要对象就创建一个:

ModernRoom room = new ModernRoom();

好了,现在现代风格房屋的对象已经有了,如果这时房屋的风格变化了,需要的是古典风格的房屋,修改一下:

ClassicalRoom room = new ClassicalRoom();

试想一下,在我们的程序中有多少处地方用到了这样的创建逻辑,而这里仅仅是房屋的风格变化了,就需要修改程序中所有的这样的语句。现在我们封装对象创建的逻辑,把对象的创建放在一个工厂方法中:

ModernFactory factory = new ModernFactory();

ModernRoom room = factory.Create();

当房屋的风格变化时,只需要修改

ClassicalFactory factory = new ClassicalFactory();

ClassicalRoom room = factory.Create();

而其它的用到room的地方仍然不变。这就是为什么需要创建型模式了。创建者模式作用可以概括为如下两点:

1.封装创建逻辑,绝不仅仅是new一个对象那么简单。

2.封装创建逻辑变化,客户代码尽量不修改,或尽量少修改。

常见的五种创建型模式

单件模式(Singleton Pattern)解决的是实体对象的个数问题,其他的都是解决new所带来的耦合关系问题。

工厂方法模式(Factory Pattern)在工厂方法中,工厂类成为了抽象类,其实际的创建工作将由其具体子类来完成。工厂方法的用意是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类中去,强调的是“单个对象”的变化。

抽象工厂模式(Abstract Factory)抽象工厂是所有工厂模式中最为抽象和最具有一般性的一种形态。抽象工厂可以向客户提供一个接口,使得客户可以在不必指定产品的具体类型的情况下,创建多个产品族中的产品对象,强调的是“系列对象”的变化。

生成器模式(Builder Pattern)把构造对象实例的逻辑移到了类的外部,在这个类的外部定义了这个类的构造逻辑。他把一个复杂对象的构造过程从对象的表示中分离出来。其直接效果是将一个复杂的对象简化为一个比较简单的目标对象。他强调的是产品的构造过程。

原型模式(Prototype Pattern)和工厂模式一样,同样对客户隐藏了对象创建工作,但是,与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。

如何选择使用创建型模式

继续考虑上面提到的游戏开发场景,假定在这个游戏场景中我们使用到的有墙(Wall),屋子(Room),门(Door)几个部件。在这个过程中,同样是对象的创建问题,但是会根据所要解决的问题不同而使用不同的创建型模式。

如果在游戏中,一个屋子只允许有一个门存在,那么这就是一个使用Signleton模式的例子,确保只有一个Door类的实例被创建。解决的是对象创建个数的问题。

示例代码:

using System;

public sealed class SigletonDoor

{

static readonly SigletonDoor instance=new SigletonDoor();

static SigletonDoor()

{

}

public static SigletonDoor Instance

{

get

{

return instance;

}

}

}

在游戏中需要创建墙,屋子的实例时,为了避免直接对构造器的调用而实例化类,这时就是工厂方法模式了,每一个部件都有它自己的工厂类。解决的是“单个对象”的需求变化问题。

示例代码:

using System;

public abstract class Wall

{

public abstract void Display();

}

public class ModernWall:Wall

{

public override void Display()

{

Console.WriteLine("ModernWall Builded");

}

}

public abstract class WallFactory

{

public abstract Wall Create();

}

public class ModernFactory:WallFactory

{

public override Wall Create()

{

return new ModernWall();;

}

}

在游戏场景中,不可能只有一种墙或屋子,有可能有现代风格(Modern),古典风格(Classical)等多系列风格的部件。这时就是一系列对象的创建问题了,是一个抽象工厂的例子。解决的是“系列对象”的需求变化问题。

示例代码:

using System;

public abstract class Wall

{

public abstract void Display();

}

public class ModernWall:Wall

{

public override void Display()

{

Console.WriteLine("ModernWall Builded");

}

}

public class ClassicalWall:Wall

{

public override void Display()

{

Console.WriteLine("ClassicalWall Builded");

}

}

public abstract class Room

{

public abstract void Display();

}

public class ModernRoom:Room

{

public override void Display()

{

Console.WriteLine("ModernRoom Builded");

}

}

public class ClassicalRoom:Room

{

public override void Display()

{

Console.WriteLine("ClassicalRoom Builded");

}

}

public abstract class AbstractFactory

{

public abstract Wall CreateWall();

public abstract Room CreateRoom();

}

public class ModernFactory:AbstractFactory

{

public override Wall CreateWall()

{

return new ModernWall();

}

public override Room CreateRoom()

{

return new ModernRoom();

}

}

public class ClassicalFactory:AbstractFactory

{

public override Wall CreateWall()

{

return new ClassicalWall();

}

public override Room CreateRoom()

{

return new ClassicalRoom();

}

}

如果在游戏场景中,构成某一个场景的算法比较稳定,例如:这个场景就是用四堵墙,一个屋子,一扇门来构成的,但具体是用什么风格的墙、屋子和门则是不停的变化的,这就是一个生成器模式的例子。解决的是“对象部分”的需求变化问题。

示例代码:

using System;

using System.Collections;

public class Director

{

public void Construct( Builder builder )

{

builder.BuildWall();

builder.BuildRoom();

builder.BuildDoor();

}

}

public abstract class Builder

{

public abstract void BuildWall();

public abstract void BuildRoom();

public abstract void BuildDoor();

public abstract GameScene GetResult();

}

public class GameBuilder : Builder

{

private GameScene g;

public override void BuildWall()

{

g = new GameScene();

g.Add( "Wall" );

}

public override void BuildRoom()

{

g.Add( "Room" );

}

public override void BuildDoor()

{

g.Add( "Door" );

}

public override GameScene GetResult()

{

return g;

}

}

public class GameScene

{

ArrayList parts = new ArrayList();

public void Add( string part )

{

parts.Add( part );

}

public void Display()

{

Console.WriteLine( " GameScene Parts:" );

foreach( string part in parts )

Console.WriteLine( part );

}

}

如果在游戏中,需要大量的古典风格或现代风格的墙或屋子,这时可以通过拷贝一个已有的原型对象来生成新对象,就是一个原型模式的例子了。通过克隆来解决“易变对象”的创建问题。

示例代码:

using System;

public abstract class RoomPrototype

{

public abstract RoomPrototype Clone();

}

public class ModernPrototype:RoomPrototype

{

public override RoomPrototype Clone()

{

return (RoomPrototype)this.MemberwiseClone();

}

}

public class ClassicalPrototype:RoomPrototype

{

public override RoomPrototype Clone()

{

return (RoomPrototype)this.MemberwiseClone();

}

}

究竟选用哪一种模式最好取决于很多的因素。使用Abstract Factory、Prototype Pattern或Builder Pattern的设计比使用Factory Method的设计更加灵活,但是也更加复杂,尤其Abstract Factory需要庞大的工厂类来支持。通常,设计以使用Factory Method开始,并且当设计者发现需要更大的灵活性时,设计便会向其他设计模式演化,当你在多个设计模式之间进行权衡的时候,了解多个设计模式可以给你提供更多的选择余地。

总结

使用创建者模式是为了提高系统的可维护性和可扩展性,提高应对需求变化的能力!

参考文献:
《设计模式中文版》
《DesignPatternsExplained》
  idior 的《你了解创建者模式了吗? --- 创建者模式详解
  MSDN WebCast:http://www.microsoft.com/china/msdn/events/webcasts/shared/Webcast/MSDNWebCast.aspx

.NET设计模式(7):创建型模式专题总结(Creational Pattern)(转)的更多相关文章

  1. .NET设计模式(7):创建型模式专题总结(Creational Pattern)

    ):创建型模式专题总结(Creational Pattern)    创建型模式专题总结(Creational Pattern) --.NET设计模式系列之七 Terrylee,2006年1月 转载: ...

  2. NET设计模式 第二部分 创建型模式(6):创建型模式专题总结(Creational Pattern)

    创建型模式专题总结(Creational Pattern) ——.NET设计模式系列之七 Terrylee,2006年1月 概述 创建型模式,就是用来创建对象的模式,抽象了实例化的过程.它帮助一个系统 ...

  3. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

  4. GoF的23种设计模式之创建型模式的特点和分类

    创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是“将对象的创建与使用分离”.这样可以降低系统的耦合度,使用者不需要关注对象的创建细节,对象的创建由相关的工厂来完成.就像我们去商场购买商品时, ...

  5. Typescript玩转设计模式 之 创建型模式

    作者简介 joey 蚂蚁金服·数据体验技术团队 前言 我们团队的工作是用单页面应用的方式实现web工具.涉及到数万到十数万行的前端代码的管理,而且项目周期长达数年. 怎么样很好地管理好这种量级的前端代 ...

  6. Python与设计模式之创建型模式及实战

    用Python学习一下设计模式,如果很枯燥的话,就强行能使用的就用一下.设计模式参考Python与设计模式-途索 1. 单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点. import ...

  7. 设计模式01 创建型模式 - 单例模式(Singleton Pattern)

    参考 [1] 设计模式之:创建型设计模式(6种) | 博客园 [2] 单例模式的八种写法比较 | 博客园 单例模式(Singleton  Pattern) 确保一个类有且仅有一个实例,并且为客户提供一 ...

  8. [C#]设计模式-单例模式-创建型模式

    单例模式用于在整个软件系统当中保持唯一实例,在 C# 当中最能够体现此概念的就是静态类,静态类的生命周期是跟随整个程序,并且在整个程序中仅保有一个实例. 不过在这里我们不再详细阐述单例模式与静态类有什 ...

  9. (转自精通Python设计模式)Python设计模式之创建型模式——2.建造者模式

    建造者模式将一个复杂对象的构造过程与其表现分离,这样,同一个构造过程可用于创建多个不同的表现. 我们来看个实际的例子,假设我们想要创建一个HMTL页面生成器,HTML页面的基本结构(构造组件)通常是一 ...

随机推荐

  1. 用C#写的读写CSV文件

    用C#写的读取CSV文件的源代码 CSV文件的格子中包含逗号,引号,换行等,都能轻松读取,而且可以把数据转化成DATATABLE格式 using System; using System.Text; ...

  2. SQLServer2005中查询语句的执行顺序

    SQLServer2005中查询语句的执行顺序   --1.from--2.on--3.outer(join)--4.where--5.group by--6.cube|rollup--7.havin ...

  3. 第一节:CLR寄宿

    本系列文章来自 CLR VIA C# .NET FrameWork在Microsoft  Windows平台的顶部运行.这意味着.NET必须用Windows可以理解的技术来构建.首先,所有的托管模块和 ...

  4. 5.python的字符串

    在前面提起过字符串这个词,现在就来学习什么是字符串. 首先,字符串是python内置的数据类型,其特点是用引号引起来,并且可以是使用单引号('字符串'),双引号("字符串"),三个 ...

  5. 第一个MySQL 存储过程

    昨天写了人生第一个mysql存储过程:遗憾的是,这个存储过程最后还是没用上,用php代码替代 话说mysql的存储过程真是反人类,不查reference,基本不能看懂那些语句:语言中能和它相比的,只有 ...

  6. LaTeX让公式跟随章节编号

    正常公式编号会是(1)(2)这种,想要编号成(3.1) (3.2)怎么办呢? \usepackage{amsmath} \numberwithin{equation}{section} 在导言区加入以 ...

  7. C语言中内存对齐方式

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  8. FineUI PK DWZ

    一.概述 FineUI(ExtAspNet)是基于 jQuery / ExtJS 的 ASP.NET 控件库. DWZ是基于JQuery的一个客户端框架. 二.比较 三.总结 这两个东西实质都是对控件 ...

  9. hdu 1872 稳定排序

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=1872 稳定排序 Description 大家都知道,快速排序是不稳定的排序方法.如果对于数组中出现的任 ...

  10. c++基础(一):数据类型和结构

    1.map map<int, int> rankDict;//定义map rankDict[1] = 5; rankDict[2] = 6;//map赋值 int dictSize = r ...