浅尝设计模式——如何使用工厂模式

本文为阅读《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类即可。

有时候我们也可以利用静态方法创建一个简单工厂,这样我们就不需要实例化工厂类。但是这样而有一个弊端,我们不能通过继承来覆盖来改变创建方法的行为(静态方法不能被覆盖)。

工厂方法模式

定义

工厂方法模式定义了一个创建对象的接口,但由子类来决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。

浅尝设计模式——如何使用工厂模式_第1张图片

示例

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;
    }
}

抽象工厂模式

定义

抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

抽象工厂为产品家族提供工厂,产品家族就是形成产品的一且组件。
浅尝设计模式——如何使用工厂模式_第2张图片

示例

现在,我们要在上面的例子上做一些改变,我们希望可以通过工厂来提供组成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;
    }
}

你可能感兴趣的:(设计模式)