Design Patterns 之工厂模式

2020-11-26 12:14:34 浏览数 (1)

现实生活中,原始社会自给自足(没有工厂),农耕社会小作坊(简单工厂,民间酒坊),工业革命流水线(工厂方法,自产自销),现代产业链代工厂(抽象工厂,富士康)。

我们的项目代码同样是由简到繁一步一步迭代而来的,但对于调用者来说,却越来越简单。

导航

    • 定义
    • 一、简单工厂模式
    • 二、工厂方法模式
    • 三、抽象工厂模式

定义

工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。

按实际业务场景划分,工厂模式有 3 种不同的实现方式,分别是简单工厂模式、工厂方法模式和抽象工厂模式。

下面我们来分别看一下这 3 种模式。

一、简单工厂模式

在简单工厂模式中创建实例的方法通常为静态(static)方法,因此 简单工厂模式 又叫作 静态工厂方法模式

简单来说,简单工厂模式有一个具体的工厂类,可以生成多个不同的产品,属于创建型设计模式。简单工厂模式不在 GoF 23 种设计模式之列。

简单工厂模式每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度,违背了“开闭原则”。

下面来看一个例子:

化妆品工厂可以生产出面霜和爽肤水。

调用方直接使用 化妆品工厂 的静态方法即可生产出化妆品。

代码语言:javascript复制
class 化妆品工厂 {
    public 化妆品 生产化妆品() {
    	化妆品 res = new 化妆品;
    	if (条件...) {
			System.out.println("化妆品工厂生成-->面霜...");
        	res = new 面霜();	
		} else () {
			System.out.println("化妆品工厂生成-->爽肤水...");
			res = new 爽肤水();
		}
		return res;
    }
}

如果我们新增一个化妆品叫做 洁面乳 ,那么我们不仅要新建一个类叫做 洁面乳 ,还要改动化妆品工厂中的代码。

这就是他的缺点,不符合开闭原则,所以 23 种设计模式中都没有它。

下面介绍他的改进版。


二、工厂方法模式

“工厂方法模式”是对简单工厂模式的进一步抽象化,其好处是可以使系统在不修改原来代码的情况下引进新的产品,即满足开闭原则。

如果要新增加一个化妆品的种类洁面乳,按照简单工厂的做法就需要新建一个类,还要 修改化妆品工厂中的代码 ,如果使用工厂方法模式,就不用修改抽象工厂中的代码了,只需要再额外增加一个具体工厂就可以了。

在抽象工厂中定义方法,然后在具体工厂中可以实现创建具体对象的逻辑。

代码语言:javascript复制
//具体工厂-面霜工厂:实现了面霜的生成方法
class 面霜工厂 implements 化妆品工厂 {
    public 化妆品 生产化妆品() {
        System.out.println("面霜工厂生成-->面霜...");
        return new 面霜();
    }
}
//具体工厂-爽肤水工厂:实现了爽肤水的生成方法
class 爽肤水工厂 implements 化妆品工厂 {
    public 化妆品 生产化妆品() {
        System.out.println("爽肤水工厂生成-->爽肤水...");
        return new 爽肤水();
    }
}

以上就是抽象方法模式。


三、抽象工厂模式

在上面的例子的基础上,如果我们还要引入化妆品的品牌,那么就会更加复杂一点,工厂方法模式已经满足不了需求了,需要使用抽象工厂模式。

之前我们讨论的都是某一个工厂只生产某一种商品,比如面霜工厂只生产面霜,但是在实际生活中,往往是同一个品牌的产品在一个工厂中生产,比如欧莱雅这个品牌的化妆品应该都是在欧莱雅工厂中生产的,纳爱斯的化妆品都是在纳爱斯工厂生产的。

抽象工厂的好处在于:对于调用者来说,不需要具体的指定某一个实现类,比如我们想要一个欧莱雅面霜,那么我们可以直接跟欧莱雅工厂说我要面霜,他生产的肯定是欧莱雅的面霜,不可能是纳爱斯的面霜。

他和工厂方法模式的区别在于,工厂方法模式的具体工厂中只能创建一个产品类,而抽象工厂模式中有很多方法,可以创建多个产品类,而且可以保证这些类都属于同一个品牌,即是同一类的。

下面仅展示具体工厂的实现代码:

代码语言:javascript复制
class 欧莱雅工厂 implements 抽象工厂 {
    public 洁面乳 生产洁面乳() {
        System.out.println("欧莱雅工厂 生成-->欧莱雅洁面乳...");
        return new 欧莱雅洁面乳();
    }
    public 爽肤水 生产爽肤水() {
        System.out.println("欧莱雅工厂 生成-->欧莱雅爽肤水...");
        return new 欧莱雅爽肤水();
    }
    public 洁面乳 生产洁面乳() {
        System.out.println("欧莱雅工厂 生成-->欧莱雅洁面乳...");
        return new 欧莱雅洁面乳();
    }
}

最后我们再来探讨一下抽象工厂模式的 开闭原则

抽象工厂模式的扩展有一定的 开闭原则 倾斜性

  • 当增加一个新的产品族时只需增加一个新的具体工厂,不需要修改原代码,满足开闭原则。
  • 当产品族中需要增加一个新种类的产品时,则所有的工厂类都需要进行修改,不满足开闭原则。

当系统中只存在一个等级结构的产品时,抽象工厂模式将退化到工厂方法模式。

0 人点赞