Head First Design Patterns -工厂模式

什么是工厂模式

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

为什么要有工厂模式

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

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店客户端中不会进行实例化

代码如下:

// 简单工厂代码
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店接口

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的制作流程

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、定义加盟商的定制化需求

public class NYPizzaStore extends PizzaStore{

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

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

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

5、main函数执行

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的抽象信息。
  • 抽象方法中对于每一个抽象接口的实现,利用了工厂方法的思路。
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值