工厂方法模式定义了一个建立对象的接口,但由子类决定要实例化的类是哪个。工厂方法让类把实例化推迟到子类。 咱们依然接着简单工厂模式提出的披萨店问题继续探讨编程
咱们假设有多种不一样的pizza店,好比纽约的pizza点,芝加哥的pizza店,他们都有本身制做的不一样种类的pizza。 若是咱们采用简单模式方法,那么咱们就须要分别创建纽约pizzafactory和芝加哥的factory等等工厂,但这样作没有弹性。咱们能不能将制做pizza的行为局限在旁pizzaStore类中,但同时又能让不一样类的点去各自实例化本身的pizza类。 显然,咱们能够将pizzaStore由一个具体类,变为一个抽象的接口:bash
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza=createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
复制代码
定义了一个抽象的基类,里面有个抽象的create方法,咱们让其余的纽约地区,芝加哥地区等等不一样的继承自这个基类,让子类本身决定怎么建立pizza。测试
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals(“cheese”)) {
return new NYStyleCheesePizza();
} else if (item.equals(“veggie”)) {
return new NYStyleVeggiePizza();
} else if (item.equals(“clam”)) {
return new NYStyleClamPizza();
} else if (item.equals(“pepperoni”)) {
return new NYStylePepperoniPizza();
} else return null;
}
}
复制代码
以上是咱们实现的一个具体的纽约pizzastore类。他继承实现了基类的抽象方法。ui
而后咱们继承实现抽象的pizza类和具体的pizza类spa
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare() {
System.out.println(“Preparing “ + name);
System.out.println(“Tossing dough...”);
System.out.println(“Adding sauce...”);
System.out.println(“Adding toppings: “);
for (int i = 0; i < toppings.size(); i++) {
System.out.println(“ “ + toppings.get(i));
}
}
void bake() {
System.out.println(“Bake for 25 minutes at 350”);
}
void cut() {
System.out.println(“Cutting the pizza into diagonal slices”);
}
void box() {
System.out.println(“Place pizza in official PizzaStore box”);
}
public String getName() {
return name;
}
}
复制代码
具体的产品类设计
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}
复制代码
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = “NY Style Sauce and Cheese Pizza”;
dough = “Thin Crust Dough”;
sauce = “Marinara Sauce”;
toppings.add(“Grated Reggiano Cheese”);
}
}
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name = “Chicago Style Deep Dish Cheese Pizza”;
dough = “Extra Thick Crust Dough”;
sauce = “Plum Tomato Sauce”;
toppings.add(“Shredded Mozzarella Cheese”);
}
void cut() {
System.out.println(“Cutting the pizza into square slices”);
}
}
复制代码
最后测试咱们的代码:code
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza(“cheese”);
System.out.println(“Ethan ordered a “ + pizza.getName() + “\n”);
pizza = chicagoStore.orderPizza(“cheese”);
System.out.println(“Joel ordered a “ + pizza.getName() + “\n”);
}
}
复制代码
工厂方法模式经常分为两大类:一个建立产品的建立类,一个产品类,其中建立类定义一个抽象的接口,外加其他的继承自他的具体实现。产品类也是相似,定义一个抽象的产品类接口,具体的产品类实现继承自基类。对象
把建立对象的代码集中在一个对象或者方法中,能够避免代码的重复,而且更方便的之后的维护,这意味着客户在实例化对象的时候,依赖的是接口,而不是具体的对象,而正是咱们以前提到的具体设计原则中的一种,针对接口编程。继承
这是咱们提出的又一设计原则:**要依赖抽象,不要依赖具体实现 ** 工厂方法模式中,就很好的应用这个原则: 若是咱们采用简单工厂模式,依赖关系是这样的:接口
而采用工厂方法模式,依赖关系如图:
这就是依赖倒置原则,高层组件依赖了底层的pizza组件!
工厂方法模式对简单工厂模式进行了抽象。有一个抽象的Factory类(能够是抽象类和接口),这个类将再也不负责具体的产品生产,而是只制定一些规范,具体的生产工做由其子类去完成。在这个模式中,工厂类和产品类每每能够依次对应。即一个抽象工厂对应一个抽象产品,一个具体工厂对应一个具体产品,这个具体的工厂就负责生产对应的产品。
工厂方法常常用在如下两种状况中: