设计模式系列之工厂模式三兄弟(Factory Pattern)

说明:设计模式系列文章是读刘伟所著《设计模式的艺术之道(软件开发人员内功修炼之道)》一书的阅读笔记。我的感受这本书讲的不错,有兴趣推荐读一读。详细内容也能够看看此书做者的博客https://blog.csdn.net/LoveLion/article/details/17517213java

工厂模式是最经常使用的一类建立型设计模式,一般咱们所说的工厂模式是指工厂方法模式,它也是使用频率最高的工厂模式。简单工厂模式是工厂方法模式的“小弟”,它不属于GoF23种设计模式,但在软件开发中应用也较为频繁,一般将它做为学习其余工厂模式的入门。此外,工厂方法模式还有一位“大哥”——抽象工厂模式。这三种工厂模式各具特点,难度也逐个加大,在软件开发中它们都获得了普遍的应用,成为面向对象软件中经常使用的建立对象的工具。编程

简单工厂模式

简单工厂模式并不属于GoF 23个经典设计模式,但一般将它做为学习其余工厂模式的基础,它的设计思想很简单。设计模式

模式定义

简单工厂模式(Simple Factory Pattern):定义一个工厂类,它能够根据参数的不一样返回不一样类的实例,被建立的实例一般都具备共同的父类。由于在简单工厂模式中用于建立实例的方法是静态(static)方法,所以简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类建立型模式。框架

简单工厂模式的要点在于:当你须要什么,只须要传入一个正确的参数,就能够获取你所须要的对象,而无须知道其建立细节。ide

模式结构图

简单工厂模式结构图以下所示:工具

简单工厂模式结构图

模式伪代码

在使用简单工厂模式时,首先须要对产品类进行重构,不能设计一个一应俱全的产品类,而需根据实际状况设计一个产品层次结构,将全部产品类公共的代码移至抽象产品类,并在抽象产品类中声明一些抽象方法,以供不一样的具体产品类来实现,典型的抽象产品类代码以下所示:学习

public abstract class Product {
    // 全部产品的公共属性

    // 全部产品类的公共业务方法
    public void methodSame() {
        //公共方法的实现
    }

    // 声明抽象业务方法
    public abstract void methodDiff();
}

具体产品类中实现了抽象产品类中声明的抽象业务方法。this

public class ConcreteProduct extends Product {
    @Override
    public void methodDiff() {
        // 具体产品业务方法的实现
    }
}

简单工厂模式的核心是工厂类,在没有工厂类以前,客户端通常会使用new关键字来直接建立产品对象,而在引入工厂类以后,客户端能够经过工厂类来建立产品,在简单工厂模式中,工厂类提供了一个静态工厂方法供客户端使用,根据所传入的参数不一样能够建立不一样的产品对象,典型的工厂类代码以下所示:.net

public class Factory {
    //静态工厂方法
    public static Product getProduct(String arg) {
        Product product = null;
        if (arg.equalsIgnoreCase("A")) {
            product = new ConcreteProductA();
            //初始化设置product
        } else if (arg.equalsIgnoreCase("B")) {
            product = new ConcreteProductB();
            //初始化设置product
        }
        return product;
    }
}

客户端代码中,咱们经过调用工厂类的工厂方法便可获得产品对象,典型代码以下所示:设计

public class Client {
    public static void main(String[] args) {
        Product product;
        product = Factory.getProduct("A"); //经过工厂类建立产品对象
        product.methodSame();
        product.methodDiff();
    }
}

模式简化

有时候,为了简化简单工厂模式,咱们能够将抽象产品类工厂类合并,将静态工厂方法移至抽象产品类中,以下图所示。

简化的简单工厂模式

客户端能够经过产品父类的静态工厂方法,根据参数的不一样建立不一样类型的产品子类对象,这种作法在JDK等类库和框架中也普遍存在。
好比:java.nio.charset.Charset

public abstract class Charset {

    /**
     * Returns a charset object for the named charset.
     */
    public static Charset forName(String charsetName) {
        java.nio.charset.Charset cs = lookup(charsetName);
        if (cs != null)
            return cs;
        throw new UnsupportedCharsetException(charsetName);
    }
}

模式小结

简单工厂模式提供了专门的工厂类用于建立对象,将对象的建立和对象的使用分离开,它做为一种最简单的工厂模式在软件开发中获得了较为普遍的应用。

使用场景:

  1. 工厂类负责建立的对象比较少,因为建立的对象较少,不会形成工厂方法中的业务逻辑太过复杂。
  2. 客户端只知道传入工厂类的参数,对于如何建立对象并不关心。

工厂方法模式

简单工厂模式虽然简单,但存在一个很严重的问题。当系统中须要引入新产品时,因为静态工厂方法经过所传入参数的不一样来建立不一样的产品,这一定要修改工厂类的源代码,将违背“开闭原则”,如何实现增长新产品而不影响已有代码?工厂方法模式应运而生。

模式定义

工厂方法模式中,咱们再也不提供一个统一的工厂类来建立全部的产品对象,而是针对不一样的产品提供不一样的工厂,系统提供一个与产品等级结构对应的工厂等级结构。工厂方法模式定义以下:

工厂方法模式(Factory Method Pattern):定义一个用于建立对象的接口,让子类决定将哪个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称做虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。工厂方法模式是一种类建立型模式。

模式结构图

工厂方法模式提供一个抽象工厂接口来声明抽象工厂方法,而由其子类来具体实现工厂方法,建立具体的产品对象。工厂方法模式结构如图所示:

工厂方法模式结构图

在工厂方法模式结构图中包含以下几个角色:

  • Product(抽象产品):它是定义产品的接口,是工厂方法模式所建立对象的超类型,也就是产品对象的公共父类。
  • ConcreteProduct(具体产品):它实现了抽象产品接口,某种类型的具体产品由专门的具体工厂建立,具体工厂和具体产品之间一一对应。
  • Factory(抽象工厂):在抽象工厂类中,声明了工厂方法(Factory Method),用于返回一个产品。抽象工厂是工厂方法模式的核心,全部建立对象的工厂类都必须实现该接口。
  • ConcreteFactory(具体工厂):它是抽象工厂类的子类,实现了抽象工厂中定义的工厂方法,并可由客户端调用,返回一个具体产品类的实例。

模式伪代码

与简单工厂模式相比,工厂方法模式最重要的区别是引入了抽象工厂角色,抽象工厂能够是接口,也能够是抽象类或者具体类,其典型代码以下所示:

public interface Factory {
    Product factoryMethod();
}

在抽象工厂中声明了工厂方法但并未实现工厂方法,具体产品对象的建立由其子类负责,客户端针对抽象工厂编程,可在运行时再指定具体工厂类,具体工厂类实现了工厂方法,不一样的具体工厂能够建立不一样的具体产品,其典型代码以下所示:

public class ConcreteFactory implements Factory {
    @Override
    public Product factoryMethod() {
        return new ConcreteProduct();
    }
}

在客户端代码中,只需关心工厂类便可,不一样的具体工厂能够建立不一样的产品,典型的客户端类代码片断以下所示:

public class Client {
    public static void main(String[] args) {
        // 肯定是哪一个工厂可获得产品
        Factory factory = new ConcreteFactory();
        // 获取产品
        Product product = factory.factoryMethod();
    }
}

模式简化

有时候,为了进一步简化客户端的使用,还能够对客户端隐藏工厂方法,此时,在工厂类中将直接调用产品类的业务方法,客户端无须调用工厂方法建立产品,直接经过工厂便可使用所建立的对象中的业务方法。

// 改成抽象类
public class AbstractFactory {
    // 在工厂类中直接调用产品类的业务方法
    public void productMethod() {
        Product product = this.createProduct();
        product.method();
    }

    public abstract Product createProduct();
}

经过将业务方法的调用移入工厂类,能够直接使用工厂对象来调用产品对象的业务方法,客户端无须直接调用工厂方法,在客户端并不关心Product细节的状况下使用这种设计方案会更加方便。

模式小结

工厂方法模式可以让工厂能够自主肯定建立何种产品对象,而如何建立这个对象的细节则彻底封装在具体工厂内部,用户只须要关心所需产品对应的工厂,无须关心建立细节,甚至无须知道具体产品类的类名。基于工厂角色产品角色的多态性设计是工厂方法模式的关键。

抽象工厂模式

工厂方法模式经过引入工厂等级结构,解决了简单工厂模式中工厂类职责过重的问题,但因为工厂方法模式中的每一个工厂只生产一类产品,可能会致使系统中存在大量的工厂类,势必会增长系统的开销。此时,咱们能够考虑将一些相关的产品组成一个产品族,由同一个工厂来统一辈子产,这就是咱们本文将要学习的抽象工厂模式的基本思想。

这里我斗胆举个例子来讲明一下吧,若是不恰当欢迎指出。

众所周知,国内知名的电器厂有海尔、海信(姑且就认为是2个),电器厂会生产电视机、电冰箱、空调(姑且就认为是3种产品)。

  • 使用工厂方法模式:工厂方法模式中每一个工厂只生产一类产品,那么就必需要有海尔电视机厂海尔电冰箱厂海尔空调厂海信电视机厂海信电冰箱厂海信空调厂
  • 使用抽象工厂模式:抽象工厂中每一个工厂生产由多种产品组成的"产品族",那么就只须要有海尔工厂海信工厂就够了,每一个工厂可生产自家的电视机、电冰箱、空调。

由此看出使用抽象工厂模式极大地减小了系统中类的个数。

模式定义

抽象工厂模式为建立一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不仅是建立一种产品,它负责建立一族产品。抽象工厂模式定义以下:

抽象工厂模式(Abstract Factory Pattern):提供一个建立一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象建立型模式。

模式结构图

在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不一样类型的产品,这些产品构成了一个产品族,抽象工厂模式结构如图所示:

抽象工厂模式结构图

在抽象工厂模式结构图中包含以下几个角色:

  • AbstractFactory(抽象工厂):它声明了一组用于建立一族产品的方法,每个方法对应一种产品。
  • ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的建立产品的方法,生成一组具体产品,这些产品构成了一个产品族,每个产品都位于某个产品等级结构中。
  • AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具备的业务方法。
  • ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

模式伪代码

在抽象工厂中声明了多个工厂方法,用于建立不一样类型的产品,抽象工厂能够是接口,也能够是抽象类或者具体类,其典型代码以下所示:

public abstract class AbstractFactory {

    public abstract AbstractProductA createProductA();

    public abstract AbstractProductB createProductB();

    public abstract AbstractProductC createProductC();
}

具体工厂实现了抽象工厂,每个具体的工厂方法能够返回一个特定的产品对象,而同一个具体工厂所建立的产品对象构成了一个产品族。对于每个具体工厂类,其典型代码以下所示:

public class ConcreteFactory1 extends AbstractFactory {
    @Override
    public AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }

    @Override
    public AbstractProductC createProductC() {
        return new ConcreteProductC1();
    }
}

模式小结

若是一开始就学习抽象工厂模式估计很难理解为何这样设计,按次序学习分析简单工厂模式工厂方法模式抽象工厂模式基本就瓜熟蒂落了。实际开发中,可能并非照搬照套工厂模式三兄弟的伪代码,大多会简化其中的部分实现。原本学习设计模式就是重思想,学习如何用抽象类、接口、拆分、组合等将软件解耦合,并加强系统可扩展性,这才是最关键的。

相关文章
相关标签/搜索