软件设计与体系结构-面向对象的设计模式-创建型模式

(一)、创建型模式概述

1.创建型模式抽象了实例化过程
2.帮助系统独立于如何创建、组合和表示对象

一个类创建型模式使用继承改变被实例化的类
类创建型模式使用继承改变被实例化的类
对象创建型模式将实例化委托给另一个对象

3.系统演化越来越依赖于对象复合而非类继承
4.两个不断出现的主旋律

将系统使用哪些具体的类的信息封装起来
隐藏这些类的实例时如何被创建和放在一起的

5.创建型模式的灵活性

什么被创建,谁创建它、怎样被创建、何时创建
允许用结构和功能差别很大的产品对象配置一个系统

6.符合单一职责原则

能够将软件模块中对象的创建和对象的使用分离
为使软件结构更加清晰,外界只需要知道对象共同的接口
无需清楚其具体的实现细节

(二)、工厂模式

定义

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
在这里插入图片描述
在工厂方法模式中,抽象产品类 Product 负责定义产品的共性,实现对事物最抽象的定义;Creator 为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreteCreator 完成的。

工厂模式的由来

(1)创建对象之前必须清楚所要创建对象的类信息,但个别情况无法达到此要求。例如,打开一个视频文件需要一个播放器对象,但用户可能不知道具体的播放器的名字,需要系统分配一个合适的播放器。
(2)为方便完成复杂的对象创建工作,引入工厂模式

工厂模式

专门负责实例化共同父类(接口)的类的实例;工厂模式可以动态决定实例化哪一个子类对象,不必实现知道要实例化哪个类。在工厂方法模式中,工厂父类定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,即通过工厂子类确定究竟实例化哪一个具体产品类。

参与者及其职责

在这里插入图片描述

参与者职责
Product定义工厂方法所创建的对象的接口
ConcreteProduct实现Product接口
Creator1.声明返回Product类型对象的工厂方法 2.可定义工厂方法的缺省实现3.可调用工厂方法创建一个Product对象
ConcreteCreator重新定义工厂方法以返回一个ConcreteProduct对象

工厂方法模式的协作

Creator依赖于其子类来定义工厂方法
通过子类的工厂方法返回合适的ConcreteProduct实例

总结

在这里插入图片描述
工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了面向对象的多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点(开-闭 原则)。在工厂方法模式中,核心的工厂类不再负责所有产品的创建,而是将具体创建工作交给子类去做。这个核心类仅仅负责给出具体工厂必须实现的接口,而不负责产品类被实例化这种细节,这使得工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

优点:

增加新的产品类无需修改现有系统,并封装了产品对象的创建细节,系统具有良好的灵活性和可扩展性。

缺点:

增加新产品时需增加新的工厂,导致系统类的个数成对增加,在一定程度上增加了系统的复杂性。

适用情况:

一个类不知道它所需要的对象的类;
一个类通过其子类来指定创建哪个对象;
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心时哪一个工厂子类创建产品子类,需要时再动态指定。

(三)、抽象工厂模式

定义

抽象工厂模式(AbstractFactoryPattern)是一种比较常用的模式,其定义如下:Provide an interface for creating families of related or dependent objects without specifying their concrete classes.(为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。)
在这里插入图片描述

抽象工厂模式的由来

(1)在软件系统中,经常面临一系列相互依赖对象的创建工作。由于需求变化,这些对象也要改变。如何像工厂模式一样提供一种封装机制来避免客户程序和多系列具体对象创建工作的紧耦合?
(2)可以将这些对象一个个通过工厂模式来创建。但是,他们相互依赖,如何保证他们的联系?
(3)实例:Windows桌面主题,当更换主题,开始按钮、任务栏等的颜色都一起变了。

抽象工厂模式

意图

提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

抽象工厂模式与工厂模式的区别

工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构。一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建 。当一个工厂等级结构可以创建出分属于不同产品等级结构的一个产品族中的所有对象时,抽象工厂模式比工厂方法模式更为简单、有效率。

参与者及其职责

在这里插入图片描述

参与者职责
AbstractFactory(抽象工厂)声明创建抽象产品对象的操作接口
ConcreteFactory(具体工厂)实现创建具体对象的操作
AbstractProduct(抽象产品)为一类产品声明一个接口
Product定义一个被具体工厂所创建的产品对象
Client(客户类)

模式分析

在这里插入图片描述
在这里插入图片描述
抽象工厂类的典型代码如下:

public abstract class AbstractFactory
{
	public abstract AbstractProductA createProductA();
	public abstract AbstractProductB createProductB();
}

具体工厂类的典型代码如下:

public class ConcreteFactory1 extends AbstractFactory
{
	public AbstractProductA createProductA()
	{
		return new ConcreteProductA1();
	}
	public AbstractProductB createProductB()
	{
		return new ConcreteProductB1();
	} 
}

总结

优点

  1. 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。另外,应用抽象工厂模式可以实现高内聚低耦合的设计目的,因此抽象工厂模式得到了广泛的应用。
  2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常实用的设计模式。
  3. 增加新的具体工厂和产品族很方便,无需修改已有系统,符合“开闭原则”。

缺点

  1. 在添加新的产品对象时,难以扩展抽象工厂以便生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。
  2. 开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)。

适用场合

  1. 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是重要的。(系统独立于其产品创建、组合和表示时)
  2. 系统中有多于一个的产品族,而每次只使用其中某一产品族。(一个系统由多个产品系列中的一个来配置时)
  3. 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。(强调一系列相关产品对象的设计以便进行联合时)
  4. 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于具体实现。(提供一个产品类库,只想显示其接口而非实现时)

(四)、建造者模式

定义

建造者模式(BuilderPattern)也叫做生成器模式,其定义如下:Separate the construction of a complex object from its representation so that the same construction process can create different representations.(将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。)
在这里插入图片描述

参与者与职责

参与者职责
Product(产品类)表示被构造的复杂对象
Builder(抽象建造者)为创建一个Product对象的各部件指定抽象接口
ConcreteBuilder(具体建造者)实现Builder接口来构造和装配产品各个部件,提供一个检索产品的接口
Director(导演类)构造一个使用Builder接口的对象

应用示例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

优点

  • 使得产品的内部表象可以独立的变化。使用Builder模式可以使客户端不必知道产品内部组成细节
  • 每一个Builder都相对独立,而与其他Builder无关
  • 可对构造过程更加精细控制
  • 将构建代码和表示代码分开

缺点

  • 难于应付 分步骤构建算法 的需求变动

适用场合

  • 相同的方法,不同的执行顺序,产生不同的事件结果时,可以采用建造者模式。
  • 多个部件或零件,都可以装配到一个对象中,但是产生的运行结果又不相同时,则可以使用该模式。
  • 产品类非常复杂,或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常非常合适。
  • 在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时,也可以采用建造者模式封装该对象的创建过程。该种场景只能是一个补偿方法,因为一个对象不容易获得,而在设计阶段竟然没有发觉,而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标。

建造者模式与工厂模式的区别

建造者模式最主要的功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了,通俗地说就是零件的装配,顺序不同产生的对象也不同;而工厂方法则重点是创建,创建零件是它的主要职责,组装顺序则不是它关心的。

(五)、单例模式

定义

Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
在这里插入图片描述
Singleton 类称为单例类,通过使用 private 的构造函数确保了在一个应用中只产生一个实例,并且是自行实例化的(在 Singleton 中自己使用 newSingleton())。

单例模式的由来

实例:

  • 系统中只能由一个窗口管理器
  • 系统中只能有一个文件系统

如何保证一个类只有一个实例并且这个实例易于被访问?一个全局变量使得一个对象可以被访问,但它不能防止实例化多个对象。
一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。

优点

由于单例模式在内存中只有一个实例,减少了内存开支,特别是一个对象需要频繁地创建、销毁时,而且创建或销毁时性能又无法优化,单例模式的优势就非常明显。

  • 由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。
  • 单例模式可以避免对资源的多重占用,例如一个写文件动作,由于只有一个实例存在内存中,避免对同一个资源文件的同时写操作。
  • 单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

缺点

  • 单例模式一般没有接口,扩展很困难,若要扩展,除了修改代码基本上没有第二种途径可以实现。单例模式为什么不能增加接呢?因为接口对单例模式是没有任何意义的,它要求“自行实例化”,并且提供单一实例、接口或抽象类是不可能被实例化的。当然,在特殊情况下,单例模式可以实现接口、被继承等,需要在系统开发中根据环境判断。
  • 单例模式对测试是不利的。在并行开发环境中,如果单例模式没有完成,是不能进行测试的,没有接口也不能使用 mock 的方式虚拟一个对象。
  • 单例模式与单一职责原则有冲突。一个类应该只实现一个逻辑,而不关心它是否是单例的,是不是要单例取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中。

适用场合

  • 当类只能有一个实例而且用户可以从一个众所周知的访问点访问它时。
  • 当该唯一实例是通过子类化可扩展的,并且客户应无需更改代码就能使用一个扩展实例时。
  • 要求生成唯一序列号的环境
  • 在整个项目中需要一个共享访问点或共享数据
  • 创建一个对象需要消耗的资源过多,如要访问 IO 和数据库等资源
  • 需要定义大量的静态常量和静态方法(如工具类)的环境

(六)、创建型模式的讨论

  • 创建型模式,就是创建对象的模式,抽象了实例化的过程。它帮助一个系统独立于如何创建、组合和表示它的那些对象。
  • 创建型模式关注的是对象的创建,创建型模式将创建对象的过程进行了抽象,也可以理解为将创建对象的过程进行了封装,作为客户程序仅仅需要去使用对象,而不再关心创建对象过程中的逻辑。
  • 所有的创建型模式都有两个永恒的主旋律:
    它们都将系统使用的哪些具体类的信息封装起来
    它们隐藏了这些类的实例是如何被创建和组织的

为什么需要创建型模式?

  • 由于设计模式的原则,面向接口进行编程,而不是实现。
  • 名称必须是构造函数,名称受限。
  • 传统的创建,每次创建都会返回一个新的对象,然而在实际项目中需要某一个类仅创建一个实例,来反复使用已经创建的对象。
  • 传统的创建中构造函数返回的类型都是具体的类型,而使用工厂模式可以返回其子类型。

在实际的系统中使用创建型模式创建对象时需要考虑到以下几点:

  • 动态地确定创建哪些对象。
  • 是谁创建这些对象,即是外部的对象,还是本身对象提供,或者静态的类继承。
  • 动态决定怎样创建对象,是新建对象或是使用Cache,还是复制某个对象。
  • 决定怎样组合或者表示这些对象。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值