工厂模式——Head First

这里主要谈论其中的工厂方法模式和抽象工厂模式。

一、定义

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

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

二、类图

工厂方法:

抽象工厂:

三、开比萨店

工厂方法:

//Creator
public abstract class PizzaStore {
    //anOperation
    public Pizza orderPizza(String type){
        Pizza pizza;
        pizza=createPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    //factoryMethod
    abstract Pizza createPizza(String type);
}

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

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

//ConcreteProduct
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");
    }
}

抽象工厂:

//AbstractFactory
public interface PizzaIngredientFactory {
    //CreateProductA
    public Dough createDough();
    //CreateProductB
    public Sauce createSauce();
    //CreateProductC
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
}

//ConcreteFactory
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();
    }
}

public abstract class Pizza {
    String name;
    String dough;
    String sauce;
    Veggies veggies[];
    Cheese cheese;
    Pepperoni pepperoni;
    Clams clam;
    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;
    }
    public String getName(){
        return name;
    }
}

//芝士比萨
public class CheesePizza extends Pizza{
    PizzaIngredientFactory ingredientFactory;
    public CheesePizza(PizzaIngredientFactory ingredientFactory){
        this.ingredientFactory=ingredientFactory;
    }
    void prepare(){
        System.out.println("Prepareing "+name);
        dough=ingredientFactory.createDough();
        sauce=ingredientFactory.createSauce();
        cheese=ingredientFactory.createCheese();
    }
}
//蛤蜊比萨
public class ClamPizza extends Pizza{
    PizzaIngredientFactory ingredientFactory;
    public ClamPizza(PizzaIngredientFactory ingredientFactory){
        this.ingredientFactory=ingredientFactory;
    }
    void prepare(){
        System.out.println("Prepareing "+name);
        dough=ingredientFactory.createDough();
        sauce=ingredientFactory.createSauce();
        cheese=ingredientFactory.createCheese();
        clam=ingredientFactory.createClam();
    }
}

public class NYPizzaStore extends PizzaStore{
    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;
    }
}

 四、适用性

工厂方法:

1、当一个类不知道它所必须创建的对象的类的时候。

2、当一个类希望由它的子类来指定它所创建的对象的时候。

3、当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

抽象工厂:

1、一个系统要独立于它的产品的创建、组合和表示时。

2、一个系统要由多个产品系列中的一个来配置时。

3、当你要强调一系列相关的产品对象的设计以便进行联合使用时。

4、当你提供一个产品类库,而只想显示它们的接口而不是实现时。

五、要点

1、所有的工厂都是用来封装对象的创建。

2、简单工厂,虽然不是真正的设计模式,但仍不失为一个简单的方法,可以将客户程序从具体类解耦。

3、工厂方法使用继承:把对象的创建委托给子类,子类实现工厂方法来创建对象。

4、抽象工厂使用对象组合:对象的创建被实现在工厂接口所暴露出来的方法中。

5、所有工厂模式都通过减少应用程序和具体类之间的依赖促进松耦合。

6、工厂方法允许类将实例化延迟到子类进行。

7、抽象工厂创建相关的对象家族,而不需要依赖它们的具体类。

8、依赖倒置原则,指导我们避免依赖具体类型,而要尽量依赖抽象。

9、工厂是很有威力的技巧,帮助我们针对抽象编程,而不要针对具体类编程。

原文地址:https://www.cnblogs.com/aaron-shu/p/5170671.html