文章目录
- 1. 定义
- 2. 类图
- 3. Java实现案例
- 3.1 抽象类:Pizza和PizzaStore
- 3.2 具体披萨:北京两种上海两种共四种
- 3.3 具体披萨店:北京店和上海店
- 3.4 测试主方法
1. 定义
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。
2. 类图
- 所以具体产品必须实现一个共同的Product接口(抽象类)
- Creator是一个抽象类,它实现了所有到操作产品的方法,但不实现工厂方法factoryMethod
- ConcreteCreator负责创建一个或多个具体Product
- 工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中
这里遵循依赖倒置的原则:要依赖抽象,不要依赖具体类
注意⚠️:在设计模式中,“实现一个接口”不一定就是指“写一个类,并利用implement关键词来实现某个java接口”,“实现一个接口”泛指实现某个超类型(类或者接口)的某个方法
3. Java实现案例
场景:
- 披萨店生产披萨
- 披萨有相同的处理流程,但有不同的处理方法,比如披萨都需要烘烤,但不同的披萨也许有不同的烘烤温度要求
- 不同的披萨店能制作的披萨类型也不同
- 易于扩展,增加新类型的披萨或新的披萨店
思考准备:
- 根据工厂方法的类图,Product即为披萨、Creator即为披萨店,因此设计抽象Class:披萨、披萨店
- 根据“工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中”,我们需要在抽象Creator中设计抽象创建披萨店方法,并由继承它的子类进行具体实现
- 易于扩展,具体披萨类继承抽象披萨类、具体披萨店类继承抽象披萨店类。
3.1 抽象类:Pizza和PizzaStore
Pizza:
package Factory;
import java.util.ArrayList;
/**
* 抽象披萨
*/
public abstract class Pizza {
String name; // 名称
String dough; // 面团类型
String sauce; // 酱料类型
ArrayList toppings = new ArrayList(); // 一套装饰品佐料
// 准备
void prepare(){
System.out.println("Preparing " + name);
System.out.println("Tossing dough..");
System.out.println("Adding sauce..");
System.out.println("Adding toppings:");
for(int i = 0; i < toppings.size(); i++){
System.out.println(" " + toppings.get(i));
}
}
// 烘焙
void bake(){
System.out.println("Bake for 30 min at 360");
}
// 分切
void cut(){
System.out.println("Cutting the pizza into diagonal slices");
}
// 打包
void box(){
System.out.println("Place pizza in official PizzaStore box");
}
public String getName(){
return name;
}
}
PizzaStore:
package Factory;
/**
* 抽象披萨商店
*/
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);
}
3.2 具体披萨:北京两种上海两种共四种
北京披萨1
package Factory;
/**
* 具体披萨
*/
public class BjStyleCheesePizza extends Pizza {
public BjStyleCheesePizza(){
name = "BeiJing Cheese Pizza";
dough = "Thin Curst Dough";
sauce = "LaoGanMa Sauce";
toppings.add("Grated Reggiano Cheese");
}
}
北京披萨2
package Factory;
/**
* 具体披萨
*/
public class BjStyleVeggiePizza extends Pizza {
public BjStyleVeggiePizza(){
name = "BeiJing Veggie Pizza";
dough = "Bj2 Dough";
sauce = "Bj2 Sauce";
toppings.add("Bj2 Cheese");
}
// 这个北京披萨覆盖了cut方法,将披萨切成正方形
@Override
void cut() {
System.out.println("Cutting the pizza into square slices");
}
}
上海披萨1
package Factory;
/**
* 具体披萨
*/
public class ShStyleCheesePizza extends Pizza {
public ShStyleCheesePizza(){
name = "Shanghai Veggie Pizza";
dough = "Sh2 Dough";
sauce = "Sh2 Sauce";
toppings.add("Sh2 Cheese");
}
}
上海披萨2
package Factory;
/**
* 具体披萨
*/
public class ShStyleVeggiePizza extends Pizza {
public ShStyleVeggiePizza(){
name = "Shanghai Veggie Pizza";
dough = "Sh2 Dough";
sauce = "Sh2 Sauce";
toppings.add("Sh2 Cheese");
}
}
3.3 具体披萨店:北京店和上海店
工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中。在本Demo中“创建对象的行为”即具体类中的createPizza方法。
北京店能生产北京的两种披萨
package Factory;
/**
* 具体披萨商店
*/
public class BeiJingPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")){
return new BjStyleCheesePizza();
} else if (type.equals("veggie")) {
return new BjStyleVeggiePizza();
}
// 等等其他类型的上海披萨
return null;
}
}
同理,上海店能生产上海店两种披萨
package Factory;
/**
* 具体披萨商店
*/
public class ShangHaiPizzaStore extends PizzaStore{
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")){
return new ShStyleCheesePizza();
} else if (type.equals("veggie")) {
return new ShStyleVeggiePizza();
}
// 等等其他类型的上海披萨
return null;
}
}
3.4 测试主方法
package Factory;
/**
* 测试主方法
*/
public class MainPizzaTest {
public static void main(String[] args) {
PizzaStore pizzaStore1 = new BeiJingPizzaStore(); // 北京披萨店
Pizza cheeseFormBj = pizzaStore1.orderPizza("cheese"); // 点一份cheese
System.out.println(cheeseFormBj.getName());
// 其他同上,如预定上海披萨店的Veggie披萨
}
}
输出:
代码结构:
参考文献:《Head First设计模式(中文版)》弗里曼