《Head First 设计模式》 学习笔记,码云同步更新中
如有错误或不足之处,请一定指出,谢谢~
目录
查看其它设计模式笔记,点这里→设计模式笔记汇总
工厂方法模式(Factory Method Pattern)
- 定义:
- 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。
工厂方法让类把实例化推迟到子类。
- 工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。
- 结构:
- Factory:抽象工厂
- ConcreteFactory:具体工厂
- Product:抽象产品
- ConcreteProduct:具体产品
- 对比简单工厂:
- 简单工厂将对象的创建逻辑写在工厂类里,那么当我们有新的对象加入时,就需要修改工厂类的代码。这不符合开闭原则。那如果我们定义一个抽象工厂类,然后将具体的对象创建过程交给子类去做,当我们引进新的产品时,只需要增加一个新的工厂类即可。显然这是要优于简单工厂模式的,这就是我们所说的工厂方法模式。
- 优点:
- 隐藏产品具体实现,用户只关心工厂,无需关心细节。
- 有新产品加入时,无需修改其他工厂和产品,只需添加新的工厂和产品。扩展性良好,完全符合“开闭原则”。
- 可结合配置文件实现对象实例化时的动态指定。
- 缺点:
- 会给系统带来更多的类,增加复杂度和额外开销。
- 案例:
- 先看上一节的简单工厂:顾客点单时,需要根据菜名创建出各种不同种类的披萨。 这些披萨都源自同一个披萨基类,不过各自有自己的口味实现。而我们创建具体的披萨对象时,只需要提供名字,不需要知道它们是如何创建的。这时就可以用到简单工厂,传递一个参数给工厂类,返回一个相应的披萨对象。
- 这时我们披萨店要扩张了,但在各个省可能会有不同的制作方法。我们希望披萨在披萨口味上加盟店有自己的决定权。但在制作流程上要受到总店的控制,比如必须使用我们品牌的盒子来装披萨等等。
- 代码:
/**
* 披萨店超类
**/
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
// 把创建披萨方法从简单工厂拿回来
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
/**
* 将实例化披萨的责任移到抽象方法中,这个方法就等同于一个工厂
* 子类通过这个方法来执行对象实例化逻辑,达到超类和子类解耦的目的
*/
abstract Pizza createPizza(String type);
}
/**
* 上海加盟店
**/
public class SHPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new SHCheesePizza();
} else if (type.equals("veggie")) {
return new SHVeggiePizza();
}
return null;
}
}
// 其他加盟店略
/**
* 披萨超类
**/
public interface Pizza {
/**
* 准备
*/
void prepare();
/**
* 烘焙
*/
void bake();
/**
* 切片
*/
void cut();
/**
* 装盒
*/
void box();
}
/**
* 上海芝士披萨
**/
public class SHCheesePizza implements Pizza{
@Override
public void prepare() {
}
@Override
public void bake() {
}
@Override
public void cut() {
}
@Override
public void box() {
System.out.println("上海风味芝士披萨完成...");
}
}
// 其他种类披萨略
/**
* 测试类
**/
public class Test {
public static void main(String[] args) {
// 首先需要一个上海披萨店
SHPizzaStore shPizzaStore = new SHPizzaStore();
// 然后点单
Pizza pizza = shPizzaStore.orderPizza("cheese");
}
}
结果:
上海风味芝士披萨完成...
网友评论