zoukankan      html  css  js  c++  java
  • 设计模式 —— 创建型模式

    创建型模式关注对象的创建过程,它将对象的创建和使用分离,在使用对象时无须知道对象的创建细节,使整个系统的设计更加符合单一职责原则

    与之相关的模式有:

    1. 简单工厂模式(思想重要,但不属于GoF23种设计模式)
    2. 工厂方法模式
    3. 抽象工厂模式
    4. 建造者模式
    5. 原型模式
    6. 单例模式

    1. 简单工厂模式(Simple Factory)

    1.1 定义

    又称静态工厂方法(Static Factory Method)模式,属于类创建型模式。
    该模式中,专门定义一个工厂类,根据参数的不同来负责创建其他类的实例。

    目的:
    为了分离对象的创建与使用而生。

    1.2模式结构

    省略部分关系箭头,仅保留继承,为了看着清晰

    该模式下包含如下角色:

    1. Factory(工厂角色)
      提供静态工厂方法,负责创建其他类实例,它返回的是抽象层的产品类,所有具体产品都是抽象产品的子类。

    2. Product(抽象产品角色)
      描述产品实例所具有的接口方法,“客户使用”以及“工厂返回”都是该抽象产品类型

    3. ConcreteProduct(具体产品角色)
      继承自抽象产品,实现接口方法

    1.3 优缺点

    优点:

    1. 客户无需知道对象具体构建细节,将创建与使用分离,对客户更加友好,系统更符合单一职责原则。
    2. 因为第1点的分离,若对象构建逻辑有所改变时,只需修改工厂逻辑即可,不用修改所有客户类。相较于以往,在一定程度上,在“开闭性”上稍有改善。
    3. 抽象产品的引入(虽不一定是模式强制引入的),使系统更加符合依赖倒转原则。

    缺点:

    1. 该单一工厂任务过重,系统扩展困难,一旦需要添加新产品,则不得不修改工厂逻辑,整个系统都可能受影响,不利于扩展和维护,不符合开闭原则。
    2. 增加了类的个数,从某方面来讲增加了系统复杂度。

    2. 工厂方法模式(Factory Method)

    2.1 定义

    "Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses."

    也称工厂模式、虚拟构造器模式(Virtual Constructor),或多态工厂模式(Polymorphic Factory),属于类创造型模式。
    该模式,抽象工厂父类定义构建产品对象的公共接口,子工厂则负责创建具体产品对象

    目的:
    为了弥补简单工厂模式的不足之处,解决单一工厂职责过重问题,使代码解耦,符合开闭原则。

    简单理解:继承了简单工厂模式优点,弥补了缺点。引入抽象工厂层,具体单个工厂只生产单一产品,客户面对抽象、接口编程。

    2.2 模式结构

    1. Product(抽象产品)
      含义同简单工厂模式

    2. ConcreteProduct(具体产品)
      某类型具体产品由专门的具体工厂创建,一一对应

    3. Factory(抽象工厂)
      声明了工厂方法(Factory Method)接口,该方法用于返回产品。

    4. ConcreteFactory(具体工厂)
      继承或实现抽象工厂,由客户调用,构建返回某一种具体产品类实例。

    2.3 优缺点

    优点:
      继承了简单工厂模式的优点,并弥补了其缺点。因为抽象工厂层的引入,以及对每种产品生产工厂的分割,使得在增改产品时,只需要添加或改动对应工厂即可,其他代码不需要做任何修改,使得系统更加依赖倒转与开闭原则。
    注:需通过反射,再配合xml配置文件或IOC来达成,即客户端不直接new具体工厂,而写入配置中,可以在一定程度上解耦

    缺点:
      每类新产品都需要对应工厂,导致类个数更多增加,某方面来看增加系统复杂度。

    3.抽象工厂模式(Abstract Factory Pattern)

    3.1 定义

    "Provide an interface for creating families of related or dependent object without specifying their concrete classes."
    提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。

    又称 Kit模式,属于对象创建型模式。

    目的:
    当存在多个产品等级结构时,传统的工厂方法模式的工厂类数量将大量增加。为了解决此问题而生

    简单理解:工厂方法模式只是该模式的特例。该模式中,工厂抽象层不只是定义一个生产单类产品的接口方法,而是用于生产产品族的一组接口方法,比如具体工厂类海尔工厂则实现3个方法,分别生产海尔电视机,海尔冰箱,海尔空调。

    相关概念:

    • 产品等级结构:即单类产品的继承结构。比如一个抽象类是空调,其具体子类为海尔空调,格力空调...,则该抽象空调与每类具体品牌空调之间构成了一个产品等级结构。
    • 产品簇:在抽象工厂模式中,产品簇是指由同一工厂生产的,位于不同产品等级结构的一组产品。如海尔空调,海尔电视机...

    3.2 模式结构

    1. AbstractFactory(抽象工厂)
      定义一组用于生成抽象产品对象的方法,每一个方法对应一个产品等级结构
    2. ConcreteFactory(具体工厂)
    3. AbstractProduct(抽象产品)
    4. ConcreteProduct(具体产品)

    3.3 优缺点

    优点:

    1. 相较于工厂方法模式,减少了类的个数。
    2. 当一个产品族种多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。这对一些需要根据当前环境来决定其行为的软件系统来说,是一种非常使用的设计模式。

    缺点:
      因为多产品构建方法糅合到了每个工厂中,导致一定程度上增加了耦合性,导致了开闭原则的“倾斜性”,即若要增加一个产品族,则只需添加一个具体工厂,无须修改其他任何代码,符合开闭原则;但若想增加一种新产品(产品等级结构),则要添加新接口方法,这将涉及到对抽象工厂及其所有子类的修改,则又不符合开闭原则。

    4. 建造者模式(Builder Pattern)

    4.1 定义

    "Separate the construction of a complex object from its representation so that the same construction process can create different representations."
    将复杂对象的构建与它的表示分离,以至于相同的构建过程可以创建不同的表示

    又称生成器模式,属于对象创建型模式。

    目的:
    为了解决复杂对象的构建问题。将复杂对象构建步骤分解,并隔离复杂对象创建与使用(或许会想着似乎与工厂相似,但实际有区别的,参照下述理解)

    简单理解:
      对于该模式完整含义,可以通过工厂方法模式来理解,工厂方法模式关注的是单类产品多个不同种类的构建,即不同的具体工厂返回不同种类的产品。而建造者模式,则是关注单个复杂对象的构建,抽象建造者定义"设置产品各个部分或属性"的接口,而不同的具体建造者通过对相同接口有着不同的实现逻辑,达到对于同种产品有着不同的构建内容。而指挥者则负责安排这些各个部分或属性接口的调用次序,构建并返回对象给客户。
    达到隔离复杂对象的创建和使用,使得相同创建过程可以创建不同产品(比如,面向抽象编程,再将具体Builder的选择配置到xml文件中获取)

    若对象各部分(即那些设置属性的接口方法)构建顺序不重要,则完全可以把指挥者合并到建造者里面去,提供一个方法以固定顺序构建和返回对象。同理,若系统只需一个具体建造者的话,则也可以省略抽象建造者。

    在实际使用中:
      Director角色往往被省略,Builder也作为静态内部类被放入产品内部(使用静态的原因,是可以不依赖于外部类实例而被创建),通过使用Builder实例中方法的链式调用,来构建产品对象。使得整体更加简单灵活。

    public class ProductObj {
        private final String mName;
        private final String mValue;
    
        private ProductObj(Builder builder) {
            this.mName = builder.name;
            this.mValue = builder.value;
        }
    
        public static class Builder {
            private String name;
            private String value;
    
            public Builder buildName(String nameObj) {
                this.name = nameObj;
                return this;
            }
    
            public Builder buildValue(String valueObj) {
                this.value = valueObj;
                return this;
            }
    
            public ProductObj build() {
                return new ProductObj(this);
            }
        }
    }
    

    CSDN:Pro_Vinny

    4.2 模式结构


    以下各角色具体含义,在上文“简单理解”中已提到,简单说一下

    1. Builder(抽象建造者)
      定义"设置产品各个部分或属性"的接口,且可以定义一个产品变量并初始化产品实例,还可以再定义一个返回产品的方法

    2. ConcreteBuilder(具体建造者)
      继承抽象建造者,不同的具体建造者根据自己业务需求实现上述接口

    3. Product(产品角色)
      复杂对象

    4. Director(指挥者)
      (若接口调用顺序不重要则可省略)由客户端创建,并由传入的具体建造者,根据一定顺序调用其“设置对象属性”的接口方法,来设置对象,最后返回对象。

    4.3 优缺点

    1. 将复杂产品的创建步骤分解在不同方法中,使得创建过程更加清晰,方便控制。
    2. 在原完整定义建造者模式下,不同具体建造者间相互独立,若想增减时无须修改其他代码,符合开闭原则。

    该模式适用于那些拥有复杂内部结构的产品,且在简化的情况下,也使得客户也更能清晰对对象的每一块进行设置。

    5. 原型模式(Prototype Pattern)

    5.1 定义

    "Specify the kind of objects to create using a prototypical instance, and create new objects by copying this prototype."
    用原型实例来确定要创建对象的类型,并通过复制原型来创建新的对象。

    属于对象创建型模式。

    目的:
    为了简化多次创建某一类型对象的过程,或保存对象中间状态。

    简单理解:在原型类中实现克隆方法(从克隆接口或者说抽象原型类继承的),客户则需要通过new或者其他方式创建一个原型对象,然后调用克隆方法即可复制得到多个相同对象。

    相关概念:

    1. Java对原型模式提供了完美支持,所有类的父类Object中提供并实现了clone()方法(相当于抽象原型类),只需在在子类中将其重写为public或protected方法,再在其中调用super.clone()即可(因为原方法是protected修饰,只有重写才能被lang包以外,以及"继承于Object的具体原型类"以外调用【具体参考java protected修饰知识】),并实现Cloneable接口(标识接口,无具体方法,否则调clone会报异常)即可。注:clone()方法为浅克隆
    2. 浅克隆:克隆对象与原对象本身不是同一个对象,但其中的对象成员变量仍指向相同的值。
    3. 深克隆:把要复制的对象,以及其所引用的对象都复制了一边。

    5.2 模式结构

    图为“带原型管理器的原型模式”(因为一般原型模式就一个clone方法,没什么好表示的)

    1. Prototype(抽象原型类)
      定义了克隆自己的方法接口,可以是抽象类或接口。

    2. ConcretePrototype(具体原型类)
      实现了克隆方法,用以复制自身返回一个克隆对象。

    3. Client(客户类)
      个人感觉该角色没必要,只要使用的地方都可以算客户,没使用也不影响“我”是可克隆的。书上定义的

    4. (可选)Prototype Manager(原型管理器)
      即原型类实例的获取不再由客户主动new或者手动调用clone(),而是由原型管理器统一管理。管理器在初始化时,则实例化所有具体原型类,并存入一个集合当中(比如键值对的形式)。当客户需要获取某个对象克隆时,则调用管理器的获取方法,该方法根据传入参数,克隆对应原型对象并返回。

    5.3 优缺点

      当需创建对象较为复杂时,或大量重复创建某对象时,可简化创建过程,提高新实例创建效率。也可适用某些需要保存对象状态的场合。个人看来无明显缺点,只是一种模式,需要的时候用即可。(教材上非要与工厂模式相比,说简化创建结构。个人感觉有些牵强,针对目标使用场景都不同)

    6. 单例模式(Singleton Pattern)

    6.1 定义

    "Ensure a class has only one instance and provide a global point of access to it"
    确保一个类只拥有一个实例,且能提供全局访问的方法。

    又称单件模式或单态模式,属于对象创建型模式。

    目的:
    当希望某个类在系统中的实例只存在一个时,可使用该模式

    6.2 模式结构

    public class LazySingleton {	//懒汉式单例模式
        private static LazySingleton instance = null;
    
        private LazySingleton(){
        }
    
        synchronized public static LazySingleton getInstance(){
            if(instance == null)
                instance = new LazySingleton();
            return instance;
        }
    }
    

      该模式只存在一个角色,即单例类本身。单例类中将构造函数私有化,防止外部调用。且定义一个自身静态成员变量用于存储实例,然后提供一个静态工厂方法供外部获取。而具体自行实例化时机,则分为 饿汉式单例类 以及懒汉式单例类。

    相关介绍:

    1. 饿汉式单例类,private static EagerSingleton instance = new EagerSingleton();即,类加载时便实例化自身。
    2. 懒汉式单例类,将实例化延迟到工厂方法被调用时。【注:必须处理好多个线程同时首次引用访问该方法的问题,因此需要通过同步化机制进行控制】

    6.3 优缺点

      将构造函数私有而自行实例化,确保了类实例的唯一性,且可对访问进行严格控制。但因为同时负责创建和业务使用,所以单例类职责过重。

  • 相关阅读:
    pgpoolII3.1 的内存泄漏(二)
    iOS 开发的一些网址
    ios开发必备第三方库
    iOS截屏方法
    ios开发第三方库cocoapods安装
    iOS开发知识点总结
    iOS开发文件夹Copy items if needed
    iOS开源库最全的整理
    iOS图标抖动效果
    iOS 加密的3种方法
  • 原文地址:https://www.cnblogs.com/simpleito/p/10880188.html
Copyright © 2011-2022 走看看