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

〇、小故事

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

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

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

一、模式定义

抽象工厂模式Abstract Factory Pattern

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

二、模式类图

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

三、代码实现

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

java 复制代码
/** 奶酪接口 **/
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

java 复制代码
/** 蛤蜊接口 **/
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

java 复制代码
/** 生面团接口 **/
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

java 复制代码
/** 调味汁接口 **/
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.java�NYPizzaingredientFactory�.javaChicagoPizzaingredientFactory�.java

java 复制代码
/** 披萨原料抽象工厂 **/
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

java 复制代码
/** 披萨抽象类 **/
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

java 复制代码
/** 奶酪口味披萨 **/
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

java 复制代码
/** 蛤蜊口味披萨 **/
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

java 复制代码
/**意大利辣肉肠口味披萨 **/
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

java 复制代码
/** 蔬菜口味披萨 **/
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

java 复制代码
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

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

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

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

工厂方法的特点

1 】采用继承 的方法实现。

2 】通过抽象方法,来通过子类实现该方法,生成对象。

抽象工厂的特点

1 】采用组合 的方法实现。

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

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

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

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

相关推荐
编程小筑1 分钟前
Clojure语言的并发编程
开发语言·后端·golang
对酒当歌丶人生几何4 分钟前
SpringBoot实现国际化
java·spring boot·后端·il8n
Code花园14 分钟前
C#语言的数据库编程
开发语言·后端·golang
weixin_437398211 小时前
Elasticsearch学习(1) : 简介、索引库操作、文档操作、RestAPI、RestClient操作
java·大数据·spring boot·后端·学习·elasticsearch·全文检索
MasterNeverDown1 小时前
spring boot controller放到那一层
java·spring boot·后端
誓约酱1 小时前
git的基本使用
linux·运维·服务器·c++·git·后端
憧憬少2 小时前
腾讯云对象存储COS自建图床并配置Obsidian自动上传
后端
AI小欧同学2 小时前
【AIGC-ChatGPT进阶提示词指令】命运之轮:一个融合神秘与智慧的对话系统设计
人工智能·后端
tan180°2 小时前
Cpp::C++11右值引用与移动构造(30)
开发语言·数据结构·c++·后端·算法
编程小筑2 小时前
Clojure语言的面向对象编程
开发语言·后端·golang