简单工厂,其实不是一种模式,而更像一种编程习惯。它封装创建对象的方法,即把new操作符替换为工厂对象的创建方法,不再使用具体实例化。
针对一个披萨店类PizzaStore,拥有多种类的披萨类Pizza,讲解简单工厂
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;
}
}
当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 目前虽然只是将原来创建的代码移过来封装一下,但是若以后添加了需要获取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();
}
}
}
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
_针对各地域原材料配比不同,所以对于同种原材料可能有多种配比方案,这样就要增加原料家族。我们来讲解一下抽象工厂模式 _
首先为工厂定义一个接口,负责创建所有的原料。
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;
}
}
此篇文章中心思想来自于《Head First 设计模式》 之工厂模式,烘烤OO的精华
如果有错误的地方,欢迎指正