创建型模式

 

(一).工厂方法:Factory Method

1.1定义:定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。针对单一结构系统.

1.2适用场景:

作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式

假如调用者自己组装产品需要增加依赖关系时,可以考虑使用工厂模式。当需要系统有比较好的扩展性时,可以考虑工厂模式

 1.3解决问题:

1.3.1Factory封装对象的创建

第一种问题是为了提高内聚(Cohesion)和松耦合(Coupling),我们经常会抽象出一些类的公共接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子类实现,达到了多态的目的。这里很容易出现的问题是 n 多的Product的子类继承自抽象基类Product,不得不在每次要用到子类的地方就编写诸如 new ConcreteProduct的代码,带来的麻烦即是:(1)客户程序员必须知道实际子类的名称如ConcreteProduct1、ConcreteProduct2等,当系统复杂后,命名将是一个很不好处理的问题(2)程序的扩展性和维护变得越来越困难,必须保存每一个对象的指针。

        为了解决上述问题,我们经常就是使用Factory模式声明一个创建对象的接口,并封装了对象的创建过程。Factory 这里类似于一个真正意义上的Factory工厂(生产对象)。如下图所示:

 

 

1.3.2Factory具体化类延迟到子类

第二种问题是在父类Factory中并不知道具体要实例化哪一个具体的子类,比如Factory类中要使用类Product(抽象父类),但Factory中并不知道具体要实例化ConcreteProduct1还是ConcreteProduct3,但在Factory类的子类ConcreteFactory中是可以知道的,故Factory类将具体化类的工作延迟到了子类ConcreteFactory中,使用newConcreteProduct1或new ConcreteProduct3。

该设计与第一种的区别在于并不是只是为了封装类Product的子类对象的创建,而是要把对象的创建延迟到子类ConcreteFactory中实现,因为有时只有子类中可以决定到底实例化哪一个类。

 

1.4总结

(1)Factory 模式在实际开发中应用非常广泛,面向对象的系统经常面临着对象创建问题:要创建的类实在是太多了,而 Factory 提供的创建对象的接口封装(第一个功能),以及其将类的实例化推迟到子类(第二个功能)都部分地解决了实际问题。

 

(2)在实现中通过参数化工厂方法fac->setFactoryMethod(3)决定是创建具体哪一个具体的Product的子类是非常有用的。

 

(3)Factory 模式带来的问题:如果为每一个具体的ConcreteProduct类的实例化提供一个函数体,那么我们可能不得不在系统中添加了一个方法来处理这个新建的 ConcreteProduct,这样 Factory 的接口永远就不肯能封闭(Close)。当然我们可以通过创建一个 Factory 的子类来通过多态实现这一点,但是这也是以新建一个类作为代价的。虽然Factory 模式对于对象的创建给予开发人员提供了很好的实现策略,但是Factory 模式仅仅局限于一类类(就是说 Product 是一类,有一个共同的基类),如果我们要为不同类的类提供一个对象创建的接口,那就要用 AbstractFactory 了。

 

(二). 抽象工厂: Factory

2.1定义:提供一个创建一系列或相关依赖对象的接口,而无需指定他们具体的类。针对多级结构.

抽象工厂模式除了具有工厂方法模式的优点外,最主要的优点就是可以在类的内部对产品族进行约束。

产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,

则几乎所有的工厂类都需要进行修改。

2.2适用场景

当需要创建的对象是一系列相互关联或相互依赖的产品族时,便可以使用抽象工厂模式。

2.3解决问题:

 AbstractFactory模式就是用来解决要创建一组相关或者相互依赖的对象的问题。如下图AbstractFactory 模式典型的结构图,其中ProductA和ProductB依赖于ConcreteFactory的对象,Product它们对象的创建被封装到用于创建对象的类ConcreteFactory中,这样只用维护一个创建对象ConcreteFactory类,比维护n多Product的相关对象的创建过程要简单的多,简化了维护的成本和工作。

 

 

2.4总结

AbstractFactory 模式和 Factory 模式的差异是使用设计模式时候的一个容易引起困惑的地方,实际上AbstractFactory 模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而 Factory 模式是为一类对象提供创建接口或延迟对象的创建到子类中实现,并且可以看到AbstractFactory 模式通常都是使用 Factory 模式实现(ConcreteFactory1)。

 

(三). 单例:Singleton

3.1定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点.

让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,

3.2适用场景

     1.外部资源:每台计算机有若干个打印机,但只能有一个PrinterSpooler,以避免两个打印作业同时输出到打印机。内部资源:大多数软件都有一个(或多个)属性文件存放系统配置,这样的系统应该有一个对象管理这些属性文件 
    2. Windows的Task Manager(任务管理器)就是很典型的单例模式(这个很熟悉吧),想想看,是不是呢,你能打开两个windows task manager吗?不信你自己试试看哦~ 
    3. windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。 
    4. 网站的计数器,一般也是采用单例模式实现,否则难以同步。 
    5. 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。 
    6. Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。 
    7. 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。 
    8. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。 
    9. 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。 
    10. HttpApplication 也是单位例的典型应用。熟悉ASP.Net(IIS)的整个请求生命周期的人应该知道HttpApplication也是单例模式,所有的HttpModule都共享一个HttpApplication实例.

3.3解决问题

Singleton 模式是为了解决获得Singleton类的唯一的实例(或变量),Singleton 模式是设计模式中最为简单、最为常见、最容易实现也是最应该熟悉和掌握的模式。在基于对象的设计中我们可以通过创建一个全局变量(对象)来实现,但全局变量在项目中是能不用就不用的,它是一个定时炸弹,是一个不安全隐患,特别是在多线程程序中,会有很多的不可预测性,同时使用全局变量,也不符合面向对象的封装原则。单例模式却能解决这些问题。

 

        下图是Singleton 模式的结构图,通过维护一个 static 的成员变量_instance来记录这个唯一的对象实例,通过提供一个 staitc 的接口Instance (程序中改为GetInstance)来获得这个唯一的实例。

 

 

3.4总结:

(1)Singleton 不可以被实例化,因此需要将构造函数声明为 protected或直接声明为 private,同时也不能delete将析构函数声明为 protected或private。

(2)Singleton 模式在开发中经常用到,并且经常和 Factory(AbstractFactory)模式在一起使用,因为系统中工厂对象只要一个用来创建对象就可以了。

(3)上述Singleton 模式没有考虑到多线程的问题,在多线程的情况下就可能创建多个Singleton实例,可以通过加互斥锁的方式解决。

(四). 建造者: Builder

4.1定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

使用建造者模式的好处

1.使用建造者模式可以使客户端不必知道产品内部组成的细节。

2.具体的建造者类之间是相互独立的,对系统的扩展非常有利。

3.由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

4.2使用建造者模式的场合:

1.创建一些复杂的对象时,这些对象的内部组成构件间的建造顺序是稳定的,但是对象的内部组成构件面临着复杂的变化。

2.要创建的复杂对象的算法,独立于该对象的组成部分,也独立于组成部分的装配方法时。

4.3解决问题

Builder 模式要解决的是:当要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要把复杂对象的创建过程和这个对象的表示(展示)分离开来。样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。

     Builder设计模式,提供一种封装机制来隔离出构成复杂对象的各个子对象的变化,从而保持系统中的相对稳定的将这些子对象组合在一起的算法不随着需求的改变而改变。

     client通过Director对象提供的接口foodInfoPoint,一步步完成套餐的定制(BuildCoolDish、BuildDrink、BuildRice),进而得到不同的套餐种类,类Builder提供不同的封装接口,具体的实现在Product中。

 

4.4总结

(1) Builder 模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

(2)Builder 模式和 AbstractFactory 模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder 模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说 Builder 模式中对象不是直接返回的。而在 AbstractFactory 模式中对象是直接返回的,AbstractFactory 模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

(五)原型:Prototype

5.1定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法.

它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

使用原型模式的另一个好处是简化对象的创建,使得创建对象就像我们在编辑文档时的复制粘贴一样简单。

因为以上优点,所以在需要重复地创建相似对象时可以考虑使用原型模式。

5.2适用场景:比如需要在一个循环体内创建对象,假如对象创建过程比较复杂或者循环次数很多的话,使用原型模式不但可以简化创建过程,而且可以使系统的整体性能提高很多。.

5.3解决问题

Prototype 模式提供了自我复制的功能,即新对象的创建可以通过已有对象进行创建(Clone),实现和具体的实现语言相关,在C++中通过拷贝构造函数(Copy Constructor)实现。拷贝构造函数中浅层拷贝和深层拷贝曾经是很多程序员的噩梦,也是修改或释放资源时程序崩溃的根源之一。

 

  在此只进行浅层拷贝的实现(intnumber),不涉及深层拷贝(主要要指有指针、复合对象的情况)。通过编译器提供的默认的拷贝构造函数(按位拷贝)的方式进行实现,重点放在Prototype 模式本身的思想。

 

 

5.4总结

Prototype 模式通过复制原型(Prototype)而获得新对象创建的功能,这里 Prototype 本身就是“对象工厂”(因为能够生产对象)。实际上 Prototype 模式和 Builder 模式、AbstractFactory 模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder 模式重在复杂对象的一步步创建(并不直接返回对象),AbstractFactory 模式重在产生多个相互依赖类的对象,而Prototype 模式重在从自身复制自己创建新类。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值