工厂模式:
当代码中有很多具体类的创建,可能就有问题。像下面这段代码,就有很多实例创建,当哪天需要修改,就要改动源码。这对代码的维护和更新代价较大。
Duck duck;
if (pinic) {
duck = new MallardDuck();
} else if (hunting) {
duck = new DecoyDuck();
} else if (inBathTub) {
duck = new RubberDuck();
}
所以还是那句话,要把改变的代码封装起来。
下面举个例子:
假如你有一家匹萨店,代码如下:
Pizza orderPizza() {
Pizza pizza = new Pizza();
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
但是当你需要增加更多匹萨类型时:
Pizza orderPizza(String type) {
Pizza pizza;
//根据不同类型创建不同pizza
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("greek")) {
pizza = new GreekPizza();
} else if (type.equals("pepperoni")) {
pizza = new PepperoniPizza();
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
很明显当我们需要改变pizza的时候会比较麻烦,需要改变的代码比较多。所以我们必须把变的代码封装起来,就是创建pizza的那部分代码。
简单工厂
所谓工厂就是创建对象。我们可以新建一个SimplePizzaFactory。当需要对象的时候,我们可以从这个工厂中获取。
public class SimplePizzaFactory {
public Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if(type.equals("peppernoi")) {
pizza = new PepperoniPizza();
} else if (type.equals("clam")) {
pizza = new ClamPizza()
} else if (type.equals("veggie")) {
pizza = new VeggiePizza();
}
return pizza;
}
}
这个时候我们的PizzaStore也需要改变下:
public class PizzaStore {
SimplePizzaFactory factory;
public PizzaStore(SimplePizzaFactory factory) {
this.factory = factory;
}
Pizza orderPizza(String type) {
Pizza pizza;
pizza = factory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
这就是简单工厂,其实这不算一种设计模式,算一种编程习惯而已
工厂方法
但是简单工厂好像破坏了原有的框架结构,但是不用简单工厂,在PiazzaStore里面创建匹萨又非常麻烦有没有一个比较好的设计模式?
我们可以在PizzaStore增加一个abstract 方法。然后每一个区域都创建一个PizzaStore的子类,来实现自己区域风格的pizza。
public abstract class PizzaStore {
Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);//抽象方法需要在每个子类中实现
}
在每个子类中实现createPizza方法,然后创建不同的Pizza。
这样框架有了,代码也解耦了。
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new NYStyleCheesePizza();
} else if(type.equals("peppernoi")) {
pizza = new NYStylePepperoniPizza();
} else if (type.equals("clam")) {
pizza = new NYStyleClamPizza()
} else if (type.equals("veggie")) {
pizza = new NYStyleVeggiePizza();
}
return pizza;
}
}
工厂方法用来处理对象的创建,并将这样的行为封装在子类中。这样,客户程序关于父类的代码和子类对象创建代码就解耦了。
abstract Product factoryMethod(String type)
具体调用如下:
PizzaStore npPizzaStore = new NYPizzaStore();
npPizzaStore.orderPizza("cheese");
然后就会调用子类的createPizza创建Pizza,接着就会
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
我们再来看下Pizza类:
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println("preareing " + name);
}
void bake () {
System.out.println("bake for 25 minutes");
}
void cut() {
System.out.println("cutting the pizza into diagonal slices")
}
void box() {
System.out.println("box")
}
public String getName() {
return name;
}
}
public class ChicagoStyleCheesePizza extends Pizza {
public ChicageStyleCheesePizza() {
name = "Chicago Pizza";
dough = "Crust Dough";
sauce = "Plum tomato Sauce";
toppings.add("cheese");
}
void cut {
System.put.println("Cutting the pizza into square slices");
}
}
定义工厂方法:
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法把类实例化推迟到子类中。
抽象工厂
现在又有新需要了,各区域使用一些自己的原料。
工厂接口:
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createDough();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
具体的工厂如下:
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese {
return new ReggianoCheese();
}
public Veggies[] createVeggies() {
Veggies veggies[] = {new Garlic(), new Onion(), new Mushroom(), new RedPerpper() };
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
再来看看抽象Pizza类,主要把perpare方法变成抽象的,并且在子类的这个方法中,收集我们需要的原料。
public abstract class Pizza {
String name;
String dough;
String sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni peppernoi;
Clams clam;
abstract void prepare() {};
void bake () {
System.out.println("bake for 25 minutes");
}
void cut() {
System.out.println("cutting the pizza into diagonal slices")
}
void box() {
System.out.println("box")
}
public String setName(String name) {
this.name = name
}
public String getName() {
return name;
}
public String toString() {
}
}
我们再来看下具体Pizza的子类实现,利用工厂创建一系列原料。
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
void prepare() {
System.out.println("preparing " +name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
再来看PizzaStore的子类:
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String type) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
if (type.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("new York Style Cheese pizza")
} else if(type.equals("peppernoi")) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("new York Style PepperoniPizza")
} else if (type.equals("clam")) {
pizza = new ClamPizza(ingredientFactory)
pizza.setName("new York Style clam pizza")
} else if (type.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("new York Style veggie pizza")
}
return pizza;
}
}
抽象工厂模式定义:
提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
这里的这个例子 ,抽象工厂是在工厂方法中的。