《HeadFirst设计模式》三、工厂模式

本文详细介绍了工厂模式,包括简单工厂和工厂方法模式。简单工厂更像编程习惯,而工厂方法模式则通过抽象方法将实例化任务交给子类,实现了创建行为的延迟。此外,文章还探讨了依赖倒置原则,强调依赖于抽象而不是具体类。通过具体的披萨店和加盟店的例子,阐述了如何应用这些设计模式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简单工厂

在这里插入图片描述

在这里的设计上,工厂通过组合的方式加入进PizzaStore,而不是继承,更能体现动态绑定的优势。

下面就是简单工厂的设计图
简单工厂,更像是一种编程习惯。还算不上设计模式,那接下来,我们再学习两个重量级的工厂模式,往下看。
在这里插入图片描述
在这里插入图片描述

二、继承的加盟店(工厂方法模式)

需求:

  1. 多一些质量控制
  2. 把加盟店和创建披萨捆绑在一起又要保持加盟店不同的风格。

做法:

  • 把create披萨放回到PizzaStore中,但是设置成抽象方法,加盟店去继承PizzaSore,实现不同的create风味。
  • 这就把做决定的行为,抛给了子类。

工厂方法模式:
定义了一个创建对象得接口,但由子类决定要实例化得类是哪一个。工厂方法让类把实例化得工作推迟到子类中。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

在这里插入图片描述

Pizza实体与其各自子类实现

package factory.pizza;

import java.util.ArrayList;

public abstract class Pizza {
    //披萨名
    String name;
    //面团类型
    String dough;
    //酱料
    String sauce;
    //一套佐料
    ArrayList toppings = new ArrayList();

    public void prepare(){
        System.out.println("Preparing " + name);
        System.out.println("Tossing " + dough);
        System.out.println("Adding sauce... " + sauce);
        System.out.println("Adding toppings : " );
        for (int i = 0; i < toppings.size();i++){
            System.out.println(" " + toppings.get(i));
        }
    }


    public void bake(){
        System.out.println("Bake for 25 minutes at 350");
    }


    public void cut(){
        System.out.println("Cutting the pizza into diagonal slices");
    }
    public void box(){
        System.out.println("Place pizza in official PizzaStore box");
    }


    public String getName() {
        return name;
    }


    @Override
    public String toString() {
        return "Pizza{" +
                "name='" + name + '\'' +
                ", dough='" + dough + '\'' +
                ", sauce='" + sauce + '\'' +
                ", toppings=" + toppings +
                '}';
    }
}

//芝加哥风味芝士披萨
public class ChicagoStyleCheesePizza extends Pizza {

    public ChicagoStyleCheesePizza() {
        name = "Chicago Style Deep Dish Cheese Pizza";
        dough = "Extra Thick Crust Dough";
        sauce = "Plum Tomato Sauce";

        toppings.add("Shredded Mozzarella Cheese");
    }

    public void cut() {
        System.out.println("Cutting the pizza into square slices");
    }
}
//纽约风味芝士披萨
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");
    }
}

PizzaStore店与其各个具体子类加盟店

public abstract class PizzaStore {


    //披萨得加工流程都是不变得
    public Pizza orderPizza(String type){
        Pizza pizza = null;
        //依赖工厂方法创建具体类,并制造出实际得披萨
        pizza = createPizza(type);
        System.out.println("--- Making a " + pizza.getName());
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }

    //创建何种披萨需要子类去实现
     abstract Pizza createPizza(String item);


}

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

public class ChicagoPizzaStore extends PizzaStore {
    @Override
    public Pizza createPizza(String item) {
        Pizza pizza = null;
        if (item.equals("cheese")) {
            return new ChicagoStyleCheesePizza();
        } else if (item.equals("veggie")) {
            return new ChicagoStyleVeggiePizza();
        } else if (item.equals("clam")) {
            return new ChicagoStyleClamPizza();
        } else if (item.equals("pepperoni")) {
            return new ChicagoStylePepperoniPizza();
        } else return null;


    }
}

快来使用这个工厂模式框架,点几份披萨

public class TestMain {
    public static void main(String[] args) {
        PizzaStore pizzaStore = new NYPizzaStore();
        Pizza pizza01 = pizzaStore.orderPizza("cheese");

        System.out.println("Jerry 得到一份披萨 : \n" + pizza01);


        PizzaStore pizzaStore02 = new ChicagoPizzaStore();
        Pizza pizza02 = pizzaStore02.orderPizza("cheese");
        System.out.println("Tom 得到一份披萨 : \n"+ pizza02);



    }
}

这样一来Jerry点到了一份纽约风味披萨,Tom点到一份芝加哥风味披萨。
PizzaStore并不知道是哪个加盟店在create披萨,Pizza也不知道到底是哪种Pizza。这都是由具体加盟店去操作的。

总结工厂方法模式:

  • 将实例化的任务推迟到具体子类,抽象类中并不知情实际的产品是哪一个产品。
  • 用户使用了哪一个子类,就创建了哪一个产品。

在这里插入图片描述

三、依赖倒置原则

  • 设计原则:要依赖抽象,不要依赖具体类。
  • 不能让高层组件依赖底层组件,并且,不管是高层还是底层,“两者” 都应该依赖于抽象。
  • 这个原则告诉我们,要依赖于抽象类,而不应该依赖于具体类。

下面是上一节的设计图,可以发现这里还有一个问题 : 每个地区的原料是不同的。
也就是说,你可以发现纽约的酱料都是纽约风格的味道,但是到了芝加哥酱料就会变成当地统一的风格。

目前代码里,酱料的生成还是由具体披萨而定,披萨种类很多,不可能每个具体披萨一创建时就制造一遍本地酱料。

在这里插入图片描述
于是,我们委托工厂替我们制作酱料,纽约的加盟店就需要去纽约原料工厂制作酱料,芝加哥的加盟店就去芝加哥工厂。
在这里插入图片描述
在这里插入图片描述
如图所示,我们把对象的new操作局限在了具体的披萨加盟店,加盟店只需要委托一个当地工厂,然后工厂负责制造原料,加盟店以及具体披萨都不需要管披萨里的原料是什么。这是原料工厂才需要关心的事。

加盟店就只需负责create一个特定口味的披萨(原料已定制)、然后prepare,bake、cut、box.就完成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_popo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值