本文为阅读《Head First 设计模式》一书的摘要总结
简单工厂并不是一个设计模式,反而比较像一种编程习惯。该习惯将代码中,实例化对象的部分封装起来,独立于客户。使得客户代码满足 关闭-开放原则。
Pizza orderPizza(String type){
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
方法的调用相对固定。所以我们可以将实例化Pizza
的部分封装起来,形成一个简单工厂:
public class SimplePizzaFactory(){
public Pizaa createPizza(String type){
if (type.equals("cheese")){
pizza = new CheesePizza();
}else if (type.equals("greek")){
pizza = new GreekPizza();
}else if (type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
}
}
public class PizzaStroe{
private SimplePizzaFactory simplePizzaFactory;
public PizzaStroe(SimplePizzaFactory simplePizzaFactory){
this.simplePizzaFactory = simplePizzaFactory;
}
Pizza orderPizza(String type){
Pizza pizza = simplePizzaFactory.createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza();
}
}
将对象实例化的过程封装起来,SimplePizzaFactory
就可以有多个客户,不仅仅是现在的PizzaStroe
,同时,以后实现改变时,只需要修改SimplePizzaFactory
类即可。
有时候我们也可以利用静态方法创建一个简单工厂,这样我们就不需要实例化工厂类。但是这样而有一个弊端,我们不能通过继承来覆盖来改变创建方法的行为(静态方法不能被覆盖)。
工厂方法模式定义了一个创建对象的接口,但由子类来决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
Product超类:
public class Pizza {
String name;
void prepare(){
System.out.println("Preparing "+ name);
System.out.println("Tossing dough...");
System.out.println("Adding sauce...");
System.out.println("Adding toppings:");
}
void back(){
System.out.println("Bake for 25 minites 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;
}
}
具体Product:
public class NYStyleClamPizza extends Pizza{
public NYStyleClamPizza() {
this.name = "NYStyleClamPizza";
}
//覆盖父类的方法,使用自己的切片方式
public void cut(){
System.out.println("Cutting the pizza into square slices");
}
}
public class NYStyleVeggiePizza extends Pizza{
public NYStyleVeggiePizza() {
this.name = "NYStyleVeggiePizza";
}
}
工厂超类:
public abstract class PizzaStory {
public Pizza orderPizza(String type){
//创建这通常会包含依赖于抽象产品的代码
Pizza pizza = createPizza(type);
pizza.prepare();
pizza.back();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
为了保证制作Pizza的流程一致,所以在超类中实现orderPizza
方法。还定义了一个抽象的 工厂方法 createPizza
,该方法由子类来负责实现,使得不同的子类可以实例化不同类型的Pizza
。
具体的工厂类:
public class NYPizzaStory extends PizzaStory{
@Override
protected Pizza createPizza(String type) {
if (type.equals("NYStyleVeggiePizza")){
return new NYStyleVeggiePizza();
}else if (type.equals("NYStyleClamPizza")){
return new NYStyleClamPizza();
}
return null;
}
}
抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂为产品家族提供工厂,产品家族就是形成产品的一且组件。
现在,我们要在上面的例子上做一些改变,我们希望可以通过工厂来提供组成Pizza
的原料。
抽象工厂:
public interface PizzaIngredientFactory{
public Dough createDough();
public Sauce createSauce();
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 RedPepper() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
抽象工厂的方法经常以工厂方法的方式实现。
Pizza
超类
public abstract class Pizza {
//每种pizza都由一组原料构成,这些原料在prepare方法中被用到
String name;
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
//这里把prepare方法定义为抽象方法,这是因为不同的Pizza类型可能由不同的成分组成,这需要有子类来实现
abstract void prepare();
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”);
}
void setName(String name) {
this.name = name;
}
String getName() {
return name;
}
}
具体的Pizza类型:
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
//我们需要工厂来为CheesePizza提供原料,所以每个Pizza类都通过构造器获得一个工厂
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
//prepare方法一步步的制作出CheesePizza,每一步所需要的原料都由原料工厂提供。而工厂具体提供的是哪种原料取决于我们提供的工厂类型。
void prepare() {
System.out.println(“Preparing “ + name);
dough = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
PizzaStore:
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory =
new NYPizzaIngredientFactory();
if (item.equals(“cheese”)) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName(“New York Style Cheese Pizza”);
} else if (item.equals(“veggie”)) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName(“New York Style Veggie Pizza”);
} else if (item.equals(“clam”)) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName(“New York Style Clam Pizza”);
} else if (item.equals(“pepperoni”)) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName(“New York Style Pepperoni Pizza”);
}
return pizza;
}
}