趣解设计模式之《小王的披萨店续集》

2023-09-30 10:14:39 浏览数 (2)

〇、小故事

在《小王的披萨店》这篇文章中,我们介绍了小王开披萨店的故事,并且为了解决多种口味披萨的扩展问题,引出了简单工厂工厂方法模式。但是,故事仍在继续,如果芝加哥的披萨店和纽约的披萨店,要求往披萨上面加的配料都不一样,那么如何可以规范多种类型披萨的创建呢?如下图所示:

【Dough】生面团 【Sauce】调味汁 【Cheese】干酪、奶酪 【Clams】蛤蜊

那么为了解决类似的问题,就可以采用我们今天要介绍的模式——抽象工厂模式。它解决了的是同一类型下多个产品族的创建。通过抽象工厂,组合了多种类型产品的创建(类似产品线)。

一、模式定义

抽象工厂模式Abstract Factory Pattern

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

二、模式类图

对于抽象工厂,将一系列产品(配料类型,比如:DoughSauceCheeseClams统一到一起去创建(即:PizzaIngredientFactory的实现类:NYPizzaingredientFactoryChicagoPizzaingredientFactory)。PizzaIngredientFactory中的createDough()createSauce()等方法,不关心底层配料如何实现,它只关系产品类型,不在意创建细节。具体类图,如下所示:

三、代码实现

奶酪原料及实现类Cheese.javaMozzarellaCheese.javaReggianoCheese.java

代码语言:javascript复制
/** 奶酪接口 **/
public interface Cheese {
    void description();
}

/** 莫泽雷勒干酪 **/
public class MozzarellaCheese implements Cheese {
    public void description() {
        System.out.println("MozzarellaCheese");
    }
}

/** 帕尔玛奶酪 **/
public class ReggianoCheese implements Cheese {
    public void description() {
        System.out.println("ReggianoCheese");
    }
}

蛤蜊原料及实现类Clams.javaFreshClams.javaFrozenClams.java

代码语言:javascript复制
/** 蛤蜊接口 **/
public interface Clams {
    void description();
}

/** 新鲜蛤蜊 **/
public class FreshClams implements Clams{
    public void description() {
        System.out.println("FreshClams");
    }
}

/** 冷冻蛤蜊 **/
public class FrozenClams implements Clams{
    public void description() {
        System.out.println("FrozenClams");
    }
}

生面团原料及实现类Dough.javaThickCrustDough.javaThinCrustDough.java

代码语言:javascript复制
/** 生面团接口 **/
public interface Dough {
    void description();
}

/** 厚的面包皮生面团 **/
public class ThickCrustDough implements Dough {
    public void description() {
        System.out.println("ThickCrustDough");
    }
}

/** 薄的面包皮生面团 **/
public class ThinCrustDough implements Dough {
    public void description() {
        System.out.println("ThinCrustDough");
    }
}

调味汁原料及实现类Sauce.javaMarinaraSauce.javaPlumTomatoSauce.java

代码语言:javascript复制
/** 调味汁接口 **/
public interface Sauce {
    void description();
}

/** 番茄酱调味汁 **/
public class MarinaraSauce implements Sauce {
    public void description() {
        System.out.println("MarinaraSauce");
    }
}

/** 梅子西红柿调味汁 **/
public class PlumTomatoSauce implements Sauce {
    public void description() {
        System.out.println("PlumTomatoSauce");
    }
}

披萨原料抽象工厂及实现类PizzaIngredientFactory.javaNYPizzaingredientFactory.javaChicagoPizzaingredientFactory.java

代码语言:javascript复制
/** 披萨原料抽象工厂 **/
public interface PizzaIngredientFactory {
    Dough createDough();
    Sauce createSauce();
    Cheese createCheese();
    Clams createClams();
}

/** 芝加哥原料工厂 **/
public class ChicagoPizzaingredientFactory implements PizzaIngredientFactory {
    public Dough createDough() {
        return new ThinCrustDough(); // 薄的面包皮生面团 
    }
    public Sauce createSauce() {
        return new MarinaraSauce(); // 番茄酱调味汁
    }
    public Cheese createCheese() {
        return new ReggianoCheese(); // 帕尔玛奶酪
    }
    public Clams createClams() {
        return new FreshClams(); // 新鲜蛤蜊
    }
}

/** 纽约原料工厂 **/
public class NYPizzaingredientFactory implements PizzaIngredientFactory {
    public Dough createDough() {
        return new ThickCrustDough(); // 厚的面包皮生面团
    }
    public Sauce createSauce() {
        return new PlumTomatoSauce(); // 梅子西红柿调味汁
    }
    public Cheese createCheese() {
        return new MozzarellaCheese(); // 莫泽雷勒干酪
    }
    public Clams createClams() {
        return new FrozenClams(); // 冷冻蛤蜊
    }
}

创建Pizza及实现类Pizza.java

代码语言:javascript复制
/** 披萨抽象类 **/
public abstract class Pizza {
    protected String name;
    protected Dough dough; // 面团
    protected Sauce sauce; // 酱
    protected Cheese cheese; // 干酪
    protected Clams clams; // 蛤蜊
    protected PizzaIngredientFactory pizzaIngredientFactory;

    /** 准备原材料 */
    public abstract void prepare();

    public void bake() {
        System.out.println("pizzaIngredientFactory bake()");
    }

    public void cut() {
        System.out.println("pizzaIngredientFactory cut()");
    }

    public void box() {
        System.out.println("pizzaIngredientFactory box()");
    }
}

奶酪口味披萨CheesePizza.java

代码语言:javascript复制
/** 奶酪口味披萨 **/
public class CheesePizza extends Pizza {

    public CheesePizza(PizzaIngredientFactory pizzaIngredientFactory) {
        this.pizzaIngredientFactory = pizzaIngredientFactory;
    }

    public void prepare() {
        System.out.println("CheesePizza prepare()");
        dough = pizzaIngredientFactory.createDough();
        sauce = pizzaIngredientFactory.createSauce();
        cheese = pizzaIngredientFactory.createCheese();
    }
}

蛤蜊口味披萨ClamPizza.java

代码语言:javascript复制
/** 蛤蜊口味披萨 **/
public class ClamPizza extends Pizza {

    public ClamPizza(PizzaIngredientFactory pizzaIngredientFactory) {
        this.pizzaIngredientFactory = pizzaIngredientFactory;
    }

    public void prepare() {
        System.out.println("ClamPizza prepare()");
        dough = pizzaIngredientFactory.createDough();
        sauce = pizzaIngredientFactory.createSauce();
        cheese = pizzaIngredientFactory.createCheese();
        // 加入蛤蜊配料
        clams = pizzaIngredientFactory.createClams();
    }
}

意大利辣肉肠口味披萨PepperoniPizza.java

代码语言:javascript复制
/**意大利辣肉肠口味披萨 **/
public class PepperoniPizza extends Pizza {

    public PepperoniPizza(PizzaIngredientFactory pizzaIngredientFactory) {
        this.pizzaIngredientFactory = pizzaIngredientFactory;
    }

    public void prepare() {
        System.out.println("PepperoniPizza prepare()");
        dough = pizzaIngredientFactory.createDough();
        sauce = pizzaIngredientFactory.createSauce();
        cheese = pizzaIngredientFactory.createCheese();
        // 加入蛤蜊配料
        clams = pizzaIngredientFactory.createClams();
    }
}

蔬菜口味披萨VeggiePizza.java

代码语言:javascript复制
/** 蔬菜口味披萨 **/
public class VeggiePizza extends Pizza {

    public VeggiePizza(PizzaIngredientFactory pizzaIngredientFactory) {
        this.pizzaIngredientFactory = pizzaIngredientFactory;
    }

    public void prepare() {
        System.out.println("VeggiePizza prepare()");
        dough = pizzaIngredientFactory.createDough();
        sauce = pizzaIngredientFactory.createSauce();
        cheese = pizzaIngredientFactory.createCheese();
    }
}

披萨工厂及实现类PizzaStoreV3.javaNYPizzaStore.java

代码语言:javascript复制
public abstract class PizzaStoreV3 {
    protected abstract Pizza createPizza(String pizzaType);

    public Pizza orderPizza(String pizzaType) {
        Pizza pizza = createPizza(pizzaType);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

public class NYPizzaStore extends PizzaStoreV3 {
    protected Pizza createPizza(String pizzaType) {
        Pizza pizza = null;
        PizzaIngredientFactory pizzaIngredientFactory = new NYPizzaingredientFactory();
        if (pizzaType.equals("cheese")) {
            pizza = new CheesePizza(pizzaIngredientFactory);
        } else if (pizzaType.equals("pepperoni")) {
            pizza = new PepperoniPizza(pizzaIngredientFactory);
        } else if (pizzaType.equals("clam")) {
            pizza = new ClamPizza(pizzaIngredientFactory);
        } else if (pizzaType.equals("veggie")) {
            pizza = new VeggiePizza(pizzaIngredientFactory);
        }
        return pizza;
    }
}

抽象工厂测试类PizzaStoreTest.java

代码语言:javascript复制
public class PizzaStoreTest {
    public static void main(String[] args) {
        PizzaStoreV3 pizzaStore = new NYPizzaStore();
        pizzaStore.orderPizza("cheese");
    }
}

四、工厂方法和抽象工厂的区别

抽象工厂的方法经常以工厂方法的方式实现。也就是说,工厂方法经常会潜伏在抽象工厂里面

工厂方法的特点

1】采用继承的方法实现。 【2】通过抽象方法,来通过子类实现该方法,生成对象。

抽象工厂的特点

1】采用组合的方法实现。 【2】通过提供接口,来创建一组产品的接口。这个接口内的每个方法都负责创建一个具体产品。

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ (^o^)/ ~ 「干货分享,每天更新」

0 人点赞