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

〇、小故事

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

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

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

一、模式定义

抽象工厂模式 (Abstract Factory Pattern)

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

二、模式类图

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

三、代码实现

奶酪�原料及实现类 :Cheese.java、MozzarellaCheese.java、ReggianoCheese.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.java、FreshClams.java、FrozenClams.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.java、ThickCrustDough.java、ThinCrustDough.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�.java、MarinaraSauce�.java、PlumTomatoSauce�.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�.java、ChicagoPizzaingredientFactory�.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.java、NYPizzaStore.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^)/ ~ 「干货分享,每天更新」

相关推荐
学长毕设4 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
滴滴答答哒5 小时前
ASP.NET Core + FaceRecognitionDotNet 人脸识别实战:DI 单例、特征向量持久化与 1:N 比对
后端·asp.net
captain3767 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
IT_陈寒9 小时前
Java序列化踩坑记:对象循环引用让我加班两小时
前端·人工智能·后端
泡海椒9 小时前
05-雷达图多维画像-信用评级多维画像
后端
王中阳Go9 小时前
5.27 分钟干完后端和全部测试:一场三小时笔试的五个失分点,四个不在代码上
大数据·数据库·人工智能·后端·大语言模型
大哥43099 小时前
Modbus 的"字序":一个配错就变成天文数字,或者干脆变成 0
后端
岩钧9 小时前
New API 源码解析:一个生产级 AI 网关的架构与实现
后端
学到老活到老9 小时前
第 24 集:配置文件写了 80,Spring Boot 为什么读到 90?
java·后端·spring
用户360055579009 小时前
Kestrel_VLLM - 25 · 全注意力层设备化、整层对拍与访存粒度
后端