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的抽象信息。
  • 抽象方法中对于每一个抽象接口的实现,利用了工厂方法的思路。
相关推荐
丁总学Java10 分钟前
--spring.profiles.active=prod
java·spring
上等猿17 分钟前
集合stream
java
java1234_小锋21 分钟前
MyBatis如何处理延迟加载?
java·开发语言
菠萝咕噜肉i22 分钟前
MyBatis是什么?为什么有全自动ORM框架还是MyBatis比较受欢迎?
java·mybatis·框架·半自动
林的快手37 分钟前
209.长度最小的子数组
java·数据结构·数据库·python·算法·leetcode
zh路西法1 小时前
【C++决策和状态管理】从状态模式,有限状态机,行为树到决策树(二):从FSM开始的2D游戏角色操控底层源码编写
c++·游戏·unity·设计模式·状态模式
向阳12181 小时前
mybatis 缓存
java·缓存·mybatis
上等猿1 小时前
函数式编程&Lambda表达式
java
夏旭泽1 小时前
设计模式-备忘录模式
设计模式·备忘录模式
蓝染-惣右介2 小时前
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
java·设计模式