Head First Design Patterns -工厂模式

什么是工厂模式

工厂方法模式定义了一个创建对象的接口,但由子类来决定要实例化那个类。工厂方法让类把实例化推迟到了子类。

为什么要有工厂模式

书中以pizza店制作pizza为例子,假设不用工厂模式,在制作pizza阶段我们需要这样去实例化类:

java 复制代码
Pizza orderPizza(String type) {
	Pizza pizza;
	
	// 基于pizza的类型,实例化具体的类,这里的每个pizza都需要实现Pizza接口
	if (type.equals("cheess")) {
		pizza = new CheesePizza();
	} else if (type.equals("greek")) {
		pizza = new GreekPizza();
	}

	// pizza的前期准备
	pizza.prepare();
	pizza.bake();
	return pizza;
}

上述代码不符合开闭原则,一旦pizza店改变pizza的供应,则需要修改上述代码

简单工厂模式

简单工厂模式并不是一种设计模式,而是一种编程习惯,定义一个工厂类,这个类封装所有披萨的对象创建,pizza店客户端中不会进行实例化

代码如下:

java 复制代码
// 简单工厂代码
public Pizza SimplePizzaFactory {
	public Pizza createPizza(String type) {
		Pizza pizza = null;
		if (type.equals("cheess")) {
			pizza = new CheesePizza();
		} else if (type.equals("greek")) {
			pizza = new GreekPizza();
		}
	}
}

// pizza店客户端代码
public class PizzaStore {
	SimplePizzaFactory factory;
	
	public PizzaStore(SimplePizzaFactory factory) {
		this.factory = factory;
	}

	public Pizza orderPizza(String type) {
		Pizza pizza;
		pizza = factory.createPizza(type);
		// pizza的前期准备
		pizza.prepare();
		pizza.bake();
		return pizza;
	}
}

简单工厂模式的类图:

简单工厂模式的优点:

  • 将变化的部分抽离出来独立形成工厂,避免在客户端直接创建

简单工厂模式的缺点:

  • 简单工厂只是提供了封装对象创建的一种方式,但没有提供工厂方法的弹性,因为它没有办法改变正在创建的产品。

工厂模式

如果pizza店引入了加盟商,加盟商对于pizza需要有一些自己的定制化需求,而上面的简单工厂模式,则不符合这种需求,需要引入工厂模式。

具体代码:

1、定义pizza店接口

java 复制代码
public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;

        pizza = createPizza(type);

        pizza.prepare();

        pizza.bake();

        pizza.cut();

        pizza.box();

        return pizza;
    }

    protected abstract Pizza createPizza(String type); // 交给子类进行实例化
}

2、 抽象pizza的制作流程

java 复制代码
public abstract class Pizza {
    String name;
    String dough;

    void prepare() {
        System.out.println("prepare finish");
    };
    void bake() {
        System.out.println("bake finish");
    };

    void cut() {
        System.out.println("cut finish");
    };

    void box() {
        System.out.println("box finish");
    };

    public String getName() {return name;};
}

3、定义加盟商的定制化需求

java 复制代码
public class NYPizzaStore extends PizzaStore{

    @Override
    public Pizza createPizza(String item) {
        if (item.equals("cheese")) {
            return new NYStyleCheesePizza();
        }else return null;
    }
}

4、定义加盟商所使用的pizza材料

java 复制代码
public class NYStyleCheesePizza extends Pizza{
    public NYStyleCheesePizza() {
        String name = "NY Style pizza";
        String dough = "thin crust dough";
        String sauce = "Marinara Sauce";
    }
}

5、main函数执行

java 复制代码
public class Main {
    public static void main(String[] args) {
        PizzaStore nyStore = new NYPizzaStore();

        Pizza pizza = nyStore.orderPizza("cheese");

    }

}

执行结果:

prepare finish

bake finish

cut finish

box finish

工厂模式的类图:

工厂模式中引入的设计原则:

  • 依赖倒置原则:依赖抽象,而不应该依赖具体类

遵循依赖倒置设计原则的指南:

  • 变量不应该持有到具体类的引用
  • 类不应该派生自具体类
  • 方法不应该覆盖任何基类的已实现方法
    (以上指南并不是铁律,要看具体的场景来遵守)

抽象工厂模式

抽象工厂模式提供一个接口来创建相关或依赖对象的家族,而并不需要指定具体的类

比较工厂方法与抽象工厂方法:

工厂方法:

抽象工厂方法:

区别:

  • 工厂方法中只会提供一个抽象接口,接口的实现交给各个工厂去做,抽象类只会知道是制作一个pizza。
  • 抽象工厂是把工厂方法中的接口给拆开了,提供抽象接口的组合。会感知到制作pizza的抽象信息。
  • 抽象方法中对于每一个抽象接口的实现,利用了工厂方法的思路。
相关推荐
缺点内向1 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅2 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看3 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程3 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t3 小时前
ZIP工具类
java·zip
lang201509284 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan5 小时前
第10章 Maven
java·maven
百锦再5 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说5 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多5 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring