简单工厂、工厂方法模式和抽象工厂模式

文章目录

  • 简单工厂(非模式,一种编程习惯)
    • 传统方式实现的PizzaStore
    • 简单工厂实现的PizzaStore
    • 小结
  • 工厂方法模式
    • 简单工厂实现两个不同地域风味的工厂
    • 工厂方法实现两个不同地域风味的工厂
  • 抽象工厂模式

除了使用new操作符之外,还有更多制造对象的方法。你将了解到实例化这个活动不应该总是公开的进行,也会认识到初始化经常造成“耦合”问题。

简单工厂(非模式,一种编程习惯)

简单工厂,其实不是一种模式,而更像一种编程习惯。它封装创建对象的方法,即把new操作符替换为工厂对象的创建方法,不再使用具体实例化

针对一个披萨店类PizzaStore,拥有多种类的披萨类Pizza,讲解简单工厂

传统方式实现的PizzaStore

public class PizzaStore {
	public Pizza orderPizza(String type) {		
		Pizza pizza = null;
		//若pizza种类增多或者移除,则此处会不停地更改
		if ("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("greek".equals(type)) {
			pizza = new GreekPizza();
		} 
		//以下步骤固定不变
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
}

传统方式实现的类图如下:
简单工厂、工厂方法模式和抽象工厂模式_第1张图片

简单工厂实现的PizzaStore

当pizza种类更新时,判断type语句块将不停的新增或者删除,这违背了“对扩展开放,对修改关闭”的原则,我们需要将这部分创建pizza的代码移出来,由一个新的对象-工厂(factory)来处理。

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

SimplePizzaFactory实现

public class SimplePizzaFactory {	
	public Pizza createPizza(String type) {		
		if ("cheese".equals(type)) {
			pizza = new CheesePizza();
		} else if ("greek".equals(type)) {
			pizza = new GreekPizza();
		} 
		return pizza;
	}
}

如下是简单工厂SimplePizzaFactory类图:
简单工厂、工厂方法模式和抽象工厂模式_第2张图片

小结

SimplePizzaFactory 目前虽然只是将原来创建的代码移过来封装一下,但是若以后添加了需要获取PizzaStoreMenu、HomeDelivery等,则可以看见简单工厂的优势啦。

工厂方法模式

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

针对一个披萨店连锁店,每个区域口味不同,制作工艺流程也会有不同的区别,但是简单工厂中制作工艺流程已经固定不变,这必然是不友好的,在此场景下,讲解工厂方法模式

简单工厂实现两个不同地域风味的工厂

比如若想创建纽约风味和芝加哥风味Pizza,代码如下:

//订购一个纽约风味Pizza
NYPizzaFacotry nyFactory = new NYPizzaFacotry();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.createPizza("Veggie");

//订购芝加哥风味Pizza
ChicagoPizzaFacotry chicagoFactory = new ChicagoPizzaFacotry();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.createPizza("Veggie"); 

不同地域的连锁店虽然采用SimplePizzaFactory创建Pizza,但是各自采用自创的流程,比如PizzaStore更换包装盒之类的,这样品牌和质量很难以保证,那么如何在保证质量的情况下又能加入自创元素呢?

工厂方法实现两个不同地域风味的工厂

之前将创建Pizza的代码封装在SimplePizzaFactory中,制作Pizza的代码封装到PizzaStore中,这样做却没有弹性。其实可以将创建和制作Pizza代码都放在PizzaStore中处理。将createPizza()设置为“抽象方法”,如下代码展示:

public abstract class PizzaStore {
	
	public Pizza orderPizza(String type) {		
		Pizza pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	
	protected abstract Pizza createPizza(String type);
	//其他方法
}

两个不同地域风味的工厂NYPizzaStore和ChicagoPizzaStore实现代码如下:

public class NYPizzaStore extends PizzaStore {
	
	public Pizza orderPizza(String type) {		
		Pizza pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	
	public Pizza createPizza(String item) {
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleViggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		}
	}
}
public class ChicagoPizzaStore extends PizzaStore {
	
	public Pizza orderPizza(String type) {		
		Pizza pizza = createPizza(type);
		pizza.prepare();
		pizza.bake();
		pizza.cut();
		pizza.box();
		return pizza;
	}
	
	public Pizza createPizza(String item) {
		if (item.equals("cheese")) {
			return new NYStyleCheesePizza();
		} else if (item.equals("veggie")) {
			return new NYStyleViggiePizza();
		} else if (item.equals("clam")) {
			return new NYStyleClamPizza();
		} else if (item.equals("pepperoni")) {
			return new NYStylePepperoniPizza();
		}
	}
}

如下是抽象类PizzaStore的类图:
简单工厂、工厂方法模式和抽象工厂模式_第3张图片

抽象工厂模式

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

_针对各地域原材料配比不同,所以对于同种原材料可能有多种配比方案,这样就要增加原料家族。我们来讲解一下抽象工厂模式 _

首先为工厂定义一个接口,负责创建所有的原料。

public interface PizzaIngredientFactory {
	public Dough createDough();
	public Sauce createSauce();
	public Cheese createCheese();
	public Viggies[] createViggies();
	public Pepperoni createPepperoni();
	public Clams createClams();
}

其次创建一个NYPizzaIngredientFactory,制作纽约专属的原材料。

public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
	
	public Dough createDough() {
		return new ThinCrustDough();
	}
	public Sauce createSauce() {
		return new MarinaraSauce();
	}
	public Cheese createCheese() { ... }
	public Viggies[] createViggies(){ ... }
	public Pepperoni createPepperoni(){ ... }
	public Clams createClams(){ ... }
	
}

然后呢,如下是Pizza类的定义:

public abstract class Pizza {
	String name;
	Dough dough;
	Sauce sauce;
	Veggies veggies[];
	Pepperoni pepperoni;
	//收集pizza所需的原料
	abstract void prepare();
	
	void bake() {
		System.out.println("bake ... ");
	}
	void cut() {
		System.out.println("cut ... ");
	}
	void box() {
		System.out.println("box ... ");
	}
	void setName(String name) {
		this.name = name;
	}
}

纽约披萨店实现如下:

public class NYPizzaStore extends PizzaStore {
	
	protected Pizza createPizza(String type) {
		Pizza pizza = null;
		PizzaIngredientFactory factory = new NYPizzaIngredientFactory();
		if (type.equals("cheese")) {
			pizza = new CheesePizza(factory);
			//
		} else if (type.equals("viggie")) {
			pizza = new ViggiePizza(factory);
			//
		} else if (type.equals("clam")) {
			pizza = new ClamPizza(factory);
			//
		}	
		return pizza;	
	}
}

抽象工厂的类图如下:
简单工厂、工厂方法模式和抽象工厂模式_第4张图片

此篇文章中心思想来自于《Head First 设计模式》 之工厂模式,烘烤OO的精华

如果有错误的地方,欢迎指正

你可能感兴趣的:(设计模式,设计模式,工厂模式)