工厂模式有三种:简单工厂模式、工厂方法模式和抽象工厂模式;
简单工厂模式:定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。
举个栗子:
咱们有一个披萨店,有很多种类的披萨。有一天一个顾客点了一份“素食披萨”。我们应该怎么下单并制作披萨呢?
先看一种low的做法:
public class PizzaStore {
public Pizza OrderPizza(String type) {
Pizza pizza;
// 选择哪种披萨
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
// 制作
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
这种把选择披萨和制作过程全放在一起,如果新推出一款披萨就要修改OrderPizza方法,不符合开闭原则。
利用简单工厂模式:
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;
}
}
// 简单工厂类
public class simplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza;
// 选择哪种披萨
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza();
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
总结:与其说简单工厂是一种模式,还不如说是一种编码习惯。就是把创建对象部分进行封装。
工厂方法模式:一个产品对应一个工厂,解决了开放封闭原则。每个工厂只能创建一个产品的实例。每次新增一个产品时,就新增一个对应的工厂。
举个栗子:
由于我们的披萨广受大家的喜爱,我们要去北京开分店啦!!!(分店就是产品)
我们需要利用简单工厂模式创建两个工厂,分别是SHPizzaFactory和BJPizzaFactory。
// 上海订一份披萨
SHPizzaFactory shFactory = new SHPizzaFactory();
PizzaStore shStore = new PizzaStore(shFactory);
shStore.orderPizza("veggie");
// 北京订了一份披萨
BJPizzaFactory bjFactory = new BJPizzaFactory();
PizzaStore bjStore = new PizzaStore(bjFactory);
bjStore.orderPizza("veggie");
如果北京的顾客和上海的顾客有不同的口味怎么办?
创建一个披萨店抽象类:
public abstract class PizzaStore {
public abstract Pizza createPizza(String type);
public Pizza orderPizza(String type) {
Pizza pizza = this.createPizza(type);
...
}
}
创建北京披萨店和上海披萨店:(允许子类做决定)
public calss BJPizzaStore extends PizzaStore {
public Pizza createPizza(String type) {
Pizza pizza;
// 选择哪种披萨
if (type.equals("cheese")) {
pizza = new BJStyleCheesePizza();
} else if (type.equals("clam")) {
pizza = new BjStyleClamPizza();
} else if (type.equals("veggie")) {
pizza = new BJStyleVeggiePizza();
}
return pizza;
}
}
public calss SHPizzaStore extends PizzaStore {
public Pizza createPizza(String type) {
Pizza pizza;
// 选择哪种披萨
if (type.equals("cheese")) {
pizza = new SHStyleCheesePizza();
} else if (type.equals("clam")) {
pizza = new ShStyleClamPizza();
} else if (type.equals("veggie")) {
pizza = new SHStyleVeggiePizza();
}
return pizza;
}
}
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体的类
一组相关的产品为一个产品族
举个栗子:
咱们的披萨店,要控制使用同样的配料,所以经讨论,需要建一个配料加工厂。不同的披萨店都从配料工厂中获取配料。
创建配料工厂接口,创建各种配料对象
public interface PizzaIngredientFactory {
public Dough createDouch();
public Sauce createSauce();
public Cheese createCheese();
}
创建一个上海配料工厂实例:
public class BJPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDouch() {
return new ThinCrustDouch();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
}
披萨抽象类:
public abstract class Pizza{
Dough dough;
Sauce sauce;
Cheese cheese;
// 准备配料
abstract void prepare();
void bake() {
System.out.println("Back for 25 minutes");
}
void cut() {
System.out.println("cut the pizza");
}
void box() {
System.out.println("Place pizza into box");
}
}
创建一个披萨实例:
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
再回到北京披萨店:
public calss BJPizzaStore extends PizzaStore {
public Pizza createPizza(String type) {
Pizza pizza;
PizzaIngredientFactory ingredientFactory = new BJPizzaIngredientFactory();
// 选择哪种披萨
if (type.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
} else if (type.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
} else if (type.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
}
return pizza;
}
}