Java设计模式学习笔记——工厂模式与抽象工厂模式

120 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

首先来看看工厂模式的概念

定义了一个创建对象的接口,由子类决定要实例化的类是哪一个,工厂方法让类把实例化推迟到子类

(例子参考自《HeadFirst设计模式》)

假设有一家披萨店,售卖多种不同的披萨,而且可以有多个加盟店,应该如何实现?

首先我们把披萨类做出来

public class Pizza {
	
	String name;
	String sauce;
	ArrayList toppings = new ArrayList();
	
	public void prepare() {
		System.out.println("准备开始做 " + name);
		System.out.println("添加调料...");
		System.out.print("添加配料:");
		for(int i = 0; i < toppings.size(); i++) {
			System.out.println(" " + toppings.get(i));
		}
	}
	
	public void bake() {
		System.out.println("放入烤箱烘烤");
	}
	
	public void cut() {
		System.out.println("切成小块");
	}
	
	public void box() {
		System.out.println("放入披萨盒中");
	}
	
	public String getName() {
		return name;
	}
}

还需要一个披萨店

public abstract class PizzaStore {
	
	public Pizza orderPizza(String type) {
		Pizza pizza;
		pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	
	public abstract Pizza createPizza(String type);
	
}

接下来创建一个店铺(总店),后续还可以有更多的加盟店,只需要继承PizzaStore这个抽象类就可以了

public class APizzaStore extends PizzaStore{

	@Override
	public Pizza createPizza(String type) {
		if(type.equals("cheese")){
			return new ACheesePizza();
		}else if(type.equals("ham")) {
			return new AHamPizza();
		}else {
			return null;
		}
	}
	
}

往这个店铺中添加几款披萨

public class AHamPizza extends Pizza{
	
	public AHamPizza() {
		name = "火腿披萨";
		sauce = "沙拉酱";
		toppings.add("优质火腿");
	}

}
public class ACheesePizza extends Pizza{
	
	public ACheesePizza() {
		name = "奶酪披萨";
		sauce = "番茄酱";
		toppings.add("优质奶酪");
	}
	
}

至此,我们就可以通过我们创建的披萨店来点餐了

public class PizzaTest {

	public static void main(String[] args) {
		//选择A店铺点餐
		PizzaStore pizzaStore = new APizzaStore();
		//选择奶酪披萨
		Pizza cheesePizza = pizzaStore.createPizza("cheese");
		//开始制作披萨
		cheesePizza.prepare();
		System.out.println("点了一个" + cheesePizza.getName());
		Pizza hamPizza = pizzaStore.createPizza("ham");
		hamPizza.prepare();
		System.out.println("再来一个" + hamPizza.getName());
	}

}

运行结果如下

20201016162048544.png

现在又多了一个新的需求,我们要确保每一家披萨店的原料是一致的,所以我们需要创建原料家族,这里我们就需要用到抽象工厂模式了

什么是抽象工厂模式?

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

先建立一个原料工厂

public interface PizzaIngredientFactory {
	
	public Sauce createSauce();
	public Cheese createCheese();
	
}

A店的原料工厂,后续可以把加盟店的原料工厂都加进来,按照需求返回不同的原料就行了

public class APizzaIngredientFactory implements PizzaIngredientFactory{

	@Override
	public Sauce createSauce() {
		// TODO Auto-generated method stub
		return new ASauce();
	}

	@Override
	public Cheese createCheese() {
		// TODO Auto-generated method stub
		return new ACheese();
	}	
	
}

披萨类

public abstract class Pizza {
	
	String name;
	Sauce sauce;
	Cheese cheese;
	
	public abstract void prepare();
	
	public void bake() {
		System.out.println("放入烤箱烘烤");
	}
	
	public void cut() {
		System.out.println("切成小块");
	}
	
	public void box() {
		System.out.println("放入披萨盒中");
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
}

A店的奶酪披萨

public class ACheese implements Cheese{
	public ACheese() {
		System.out.println("用到了ACheese奶酪");
	}
}

A店的甜酱披萨

public class ASauce implements Sauce{
	public ASauce() {
		System.out.println("用了ASauce调料");
	}
}

还得稍微修改一下A披萨店

public class APizzaStore extends PizzaStore{

	@Override
	public Pizza createPizza(String type) {
		// TODO Auto-generated method stub
		Pizza pizza = null;
		PizzaIngredientFactory ingredientFactory = new APizzaIngredientFactory();
		if(type.equals("cheese")) {
			pizza = new CheesePizza(ingredientFactory);
			pizza.setName("奶酪披萨");
		}else if(type.equals("sauce")) {
			pizza = new SaucePizza(ingredientFactory);
			pizza.setName("甜酱披萨");
		}
		return pizza;
	}

}

具体的原材料像奶酪,火腿这些需要自己分别声明一个接口,各种不同品种的奶酪和火腿实现对应的接口来满足不同的风味就行了,这里代码就不展示了

最后来测试一下

public class PizzaTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		PizzaStore aPizzaStore = new APizzaStore();
		Pizza pizza = aPizzaStore.orderPizza("cheese");
	}

}

20201016163046944.png