[设计模式]工厂模式——抽象工厂

简介

根据《head first 设计模式》所述,工厂模式共有三种:静态工厂方法工厂方法、抽象工厂。本文介绍抽象工厂。

1、定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。

2、满足的OO原则——依赖倒置原则:要依赖抽象,不要依赖具体类。

3、模式结构:工厂类(抽象工厂和具体工厂)和产品类(抽象产品和具体产品)

4、具体实现(完整代码):

同样是做披萨系统,工厂方法是以披萨店为抽象进行设计,这样一个地区的披萨风味可以作为一个具体创建者类来实现,我们可以随意增加一个披萨风味,但是这样的话,可扩展性还是不够,因为如果新出现的一个披萨风味用了不同的原料的话,我们依然需要更改抽象产品类(Pizza)以及具体产品类进行扩充。而抽象工厂则是以原料抽象出来作为工厂进行设计,这样我们需要创建原料类(抽象工厂类),再选择不同的原料进行生产披萨即可,如果原料有所增加或者减少的话,我们只要更改原料类即可,同时这样的更改不会影响到其他的类。(而工厂方法中,如果减少原料的话,可能要更改一批涉及此原料的具体产品类,这是一个比较大的改动)

  • 抽象工厂类:定义了一个接口,所有的具体工厂都必须实现此接口,所有的具体工厂都必须实现此接口,这个接口包含一组方法用来生产产品。
public interface PizzaIngredientFactory{
    public Dough createDough();
    public Sauce createSauce();
    public Cheese createCheese();
    public Veggies[] createVeggies();
    public Pepperoni createPepperoni();
    public Clams createClam();
}
  • 具体工厂类:实现不同的产品家族,要创建一个产品,客户只要使用其中的一个工厂而完全不需实例化任何产品对象。
//制作芝加哥披萨的原料工厂
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory{
    //面团
    public Dough createDough(){
        return new ThickCrustDough();
    }
    //酱料
    public Sauce createSauce(){
        return new PlumTomatoSauce();
    }
    //芝士
    public Cheese createCheese(){
        return new MozzarellaCheese();
    }
    //蔬菜
    public Veggies[] createVeggies(){
        Veggies veggies[] = {new Spinach(),new BlackOlives(),new EggPlant()};
        return veggies;
    }
    //意式腊肠
    public Pepperoni createPepperoni(){
        return new SlicedPepperoni();
    }
    //蛤蜊
    public Clams createClam(){
        return new FrozenClams();
    }
}

//制作纽约披萨的原料工厂
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 interface Dough{
    public String toString();
}

//原料:意式腊肠
public interface Pepperoni{
    public String toString();
}
  • 具体产品类:
//面团:厚面团
public class ThickCrustDough implements Dough{
    public String toString(){
        return "Thick Crust Dough";
    }
}

//面团:薄面团
public class ThinCrustDough implements Dough{
    public String toString(){
        return "Thin Crust Dough";
    }
}

//意式腊肠:腊肠片
public class SlicedPepperoni implements Pepperoni{
    public String toString(){
        return "Sliced Pepperoni";
    }
}
  • 客户端:客户的代码中只需设计抽象工厂,运行时将自动使用实际的工厂。
//纽约风味的披萨饼
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;
    }
}

//芝加哥风味的披萨饼
public class ChicagoPizzaStore extends PizzaStore{
    protected Pizza createPizza(String item){
        Pizza pizza = null;
        PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory();

        if(item.equals("cheese")){
            pizza = new CheesePizza(ingredientFactory);
            pizza.setName("Chicago Style Cheese Pizza");
        }else if(item.equals("veggie")){
            pizza = new VeggiePizza(ingredientFactory);
            pizza.setName("Chicago Style Veggie Pizza");
        }else if(item.equals("clam")){
            pizza = new ClamPizza(ingredientFactory);
            pizza.setName("Chicago Style Clam Pizza");
        }else if(item.equals("pepperoni")){
            pizza = new PepperoniPizza(ingredientFactory);
            pizza.setName("Chicago Style Pepperoni Pizza");
        }
        return pizza;
    }
}

5、抽象工厂优点:可以把一群相关的产品集合起来

6、抽象工厂缺点:增加新种类的产品比较困难。

7、工厂方法和抽象工厂的区别:

  • 工厂方法使用类,而抽象工厂使用对象
  • 工厂方法使用继承来创建对象,而抽象工厂通过对象的组合来创建对象。

    注:二者都负责将客户从具体类型中解耦,但方法不同:工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法;而抽象工厂提供一个用来创建一个产品家族的抽象类型,这个类型的子类定义了产品被产生的方法,要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。

 

参考资料

[1] head first 设计模式

posted @ 2020-03-13 20:40  justDoIT&  阅读(249)  评论(0编辑  收藏  举报