实例化这个活动不应该总是公开地进行,初始化经常造成“耦合问题”。使用new时,即实例化一个具体类,而代码绑着具体类则会导致代码更脆弱,缺乏弹性。除了使用 new 操作符以外,还有很多创建对象的方法。
针对接口编程,可以隔离掉以后系统中可能发生的一大堆改变,因为通过多态,它可以与任何新类实现该接口。
工厂可以将常见对象的代码集中在一个方法或对象中,可以避免代码重复,并且更方便以后的维护。这也意味着,客户在实例化对象时,只会依赖接口,而不是具体类,将客户代码与真实的实现解耦。但在工厂代码中,不可避免地使用具体类来实例化真正的对象,Y?对象的创建是现实的,如果不创建任何对象,就无法创建任何程序。然而利用工厂,可将这些创建对象的代码集中管理。
下面依次介绍简单工厂,工厂方法模式,抽象工厂模式。
简单工厂:将实例化具体类的代码从客户代码中剥离,单独写一个类来处理对象的创建,原来的代码用简单工厂来获取对象。
代码示例:
代码A:
public class PizzaStore { Pizza OrderPizza(string type) { Pizza pizza;
if (type.equals("cheese")) // 蓝色代码部分将使用简单工厂来创建对象: pizza = new CheesePizza(); // pizza = SimplePizzaFactory.CreatePizza(type); else if (type.equals("greek")) pizza = new GreekPizza(); pizza.prepair(); pizza.bake(); pizza.box(); } }
将上述蓝色字体部分提炼成简单工厂:
代码B:
public class SimplePizzaFactory { public static Pizza CreatePizza(string type) { Pizza pizza; if (type.equals("cheese")) pizza = new CheesePizza(); else if (type.equals(“greek”)) pizza = new GreekPizza(); } return pizza; }
这样做的作用?(似乎只是将问题搬到另一个对象中罢了):把创建pizza的代码包装进一个类中,当以后实现改变时,只需修改这个类即可,同时也将具体实例化的过程从客户代码中删除,即解耦!
工厂方法模式:定义了一个创建对象的接口,但由子类来决定要实例化的具体类是哪一个。工厂方法让类实例化推迟到子类。
代码示例:针对代码A进行改善
代码C:
public abstract class PizzaStore { public Pizza OrderPizza(string type) { Pizza pizza = CreatePizza(type); pizza.prepair(); pizza.bake(); pizza.box(); } // 现在将工厂对象移到这个方法中; // 工厂方法是抽象的,所以依赖子类来创建具体对象; // 工厂方法必须返回一个产品(Pizza),超类中定义的方法,通常使用到这个产品; // 工厂方法将客户代码(超类中的代码)和实际创建对象的代码分隔开,即解耦。 abstract Pizza CreatePizza(string type); }
该做法可以让制作活动局限于PizzaStore类,并且能够建立一个框架,将PizzaStore和CreatePizza绑到一起,同时又保持一定的弹性。
编写一个子类(真正创建对象的代码)
public class NYPizzaStore extends PizzaStore { Pizza CreatePizza(string type) { if (type.equals("cheese")) return new NYCheesePizza(); else if (type.equals("greek")) new NYGreekPizza(); } }
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
代码示例:针对代码A进行改善
代码D:
public interface PizzaIngredientFactory { public Dough CreateDough(); public Sauce CreateSauce(); public Cheese CreateCheese(); }
在编写一个具体类实现该接口
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {...}
在该接口中,每个原料都有一个对应的方法创建自己,这些方法都类似工厂方法(都在“子类”中创建真正对象)。