【设计模式】23种设计模式之工厂模式

本文介绍了工厂模式,一种将对象的创建与使用相分离的设计模式。通过示例展示了如何使用工厂模式在不同工厂中创建不同类型的产品,如纽约和芝加哥的披萨。这种模式使得客户只需知道工厂名称即可获取所需产品,增强了灵活性,同时也遵循了开闭原则。然而,它也存在类数量过多和理解难度增加的缺点。
摘要由CSDN通过智能技术生成

工厂模式

​ 在现实生活中社会分工越来越细,越来越专业化。各种产品有专门的工厂生产,彻底告别了自给自足的小农经济时代,这大大缩短了产品的生产周期,提高了生产效率。同样,在软件开发中能否做到软件对象的生产和使用相分离呢?能否在满足“开闭原则”的前提下,客户随意增删或改变对软件相关对象的使用呢?这就是本节要讨论的问题。

定义

工厂模式定义了一个创建对象的接口(抽象基类),但由子类决定要示例化的类是哪一个。工厂方法模式让类把实例化推迟到子类。

UML类图

在这里插入图片描述

使用场景

1.客户只知道创建产品的工厂名,而不知道具体的产品名。如 TCL 电视工厂、海信电视工厂等。

2.创建产品的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口。

3.客户不关心创建产品的细节,只关心产品的品牌。

示例

以下是工厂类:

Pizza工厂基类

/**
 * 产品工厂基类
 */
public abstract class PizzaFactory {

    /**
     * 根据Type创建不同的产品
     *
     * @param type 产品类型
     * @return
     */
    public Pizza createProduct(String type) {
        Pizza pizza;
        // 生产Pizza产品
        pizza = createPizza(type);
        // 对Pizza产品做一些操作
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        // 返回生产的产品
        return pizza;
    }

    protected abstract Pizza createPizza(String type);
}

纽约Pizza工厂

/**
 * 纽约Pizza工厂
 */
public class NYPizzaFactory extends PizzaFactory {
    @Override
    protected Pizza createPizza(String type) {
        Pizza pizza = null;
        switch (type) {
            case "Cheese":
                pizza = new NYStlyeCheesePizza();
                break;
            case "Clam":
                pizza = new NYStyleClamPizza();
                break;
        }
        return pizza;
    }
}

芝加哥Pizza工厂

/**
 * 芝加哥Pizza工厂
 */
public class ChicagoPizzaFactory extends PizzaFactory {

    @Override
    protected Pizza createPizza(String type) {
        Pizza pizza= null;
        switch (type){
            case "Cheese":
                pizza = new ChicagoCheesePizza();
                break;
            case "Clam":
                pizza = new ChicagoClamPizza();
                break;
        }
        return pizza;
    }
}

以下是产品类:

Pizza基类

/**
 * 披萨基类
 */
public class Pizza {
    protected String name; // 名称
    protected String dough; // 面团
    protected String sauce; // 酱料
    protected List<String> topping = new ArrayList(); // 配料

    public void prepare() {
        // 准备
        System.out.println("正在准备的Pizza:" + name);
    }

    public void bake() {
        // 烘培
        System.out.println("烘培需要30分钟..");
    }

    public void cut() {
        // 切片
        System.out.println("正在切片...");
    }

    public void box() {
        // 装盒
        System.out.println("Pizza装进方盒..");
    }

    public String getName() {
        return name;
    }
}

纽约奶酪Pizza

/**
 * 纽约奶酪Pizza
 */
public class NYStlyeCheesePizza extends Pizza {

    public NYStlyeCheesePizza(){
        name = "纽约奶酪Pizza";
        dough = "纽约面团";
        sauce  = "纽约酱料";
        topping.add("纽约佐料");
    }

    @Override
    public void cut(){
        System.out.println("纽约奶酪Pizza要切成圆形...");
    }
}

纽约蛤蜊Pizza

/**
 * 纽约蛤蜊Pizza
 */
public class NYStyleClamPizza extends Pizza {

    public NYStyleClamPizza(){
        name = "纽约蛤蜊Pizza";
        dough = "纽约面团";
        sauce  = "纽约酱料";
        topping.add("纽约佐料");
    }

    @Override
    public void cut(){
        System.out.println("纽约蛤蜊Pizza要切成圆形...");
    }
}

芝加哥奶酪Pizza

/**
 * 芝加哥奶酪Pizza
 */
public class ChicagoCheesePizza extends Pizza {
    public ChicagoCheesePizza(){
        name = "芝加哥奶酪Pizza";
        dough = "芝加哥面团";
        sauce  = "芝加哥酱料";
        topping.add("芝加哥佐料");
    }

    @Override
    public void cut(){
        System.out.println("芝加哥奶酪Pizza要切成方形...");
    }
}

芝加哥蛤蜊Pizza

/**
 * 芝加哥蛤蜊Pizza
 */
public class ChicagoClamPizza extends Pizza {

    public ChicagoClamPizza(){
        name = "芝加哥蛤蜊Pizza";
        dough = "芝加哥面团";
        sauce  = "芝加哥酱料";
        topping.add("芝加哥佐料");
    }

    @Override
    public void cut(){
        System.out.println("芝加哥蛤蜊Pizza要切成方形...");
    }
}

测试:

/**
 * 测试
 */
public class Test {
    public static void main(String[] args) {
        // 用纽约Pizza工厂生产一个纽约蛤蜊Pizza
        NYPizzaFactory nyPizzaFactory = new NYPizzaFactory();
        Pizza nyClamPizza = nyPizzaFactory.createProduct("Clam");

        // 用芝加哥Pizza工厂生产一个芝加哥奶酪Pizza
        ChicagoPizzaFactory chicagoPizzaFactory = new ChicagoPizzaFactory();
        Pizza chicagoCheesePizza = chicagoPizzaFactory.createProduct("Cheese");
    }
}

结果:

正在准备的Pizza:纽约蛤蜊Pizza
烘培需要30分钟..
纽约蛤蜊Pizza要切成圆形...
Pizza装进方盒..
正在准备的Pizza:芝加哥奶酪Pizza
烘培需要30分钟..
芝加哥奶酪Pizza要切成方形...
Pizza装进方盒..

优缺点

优点:

1.用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程。

2.灵活性增强,对于新产品的创建,只需多写一个相应的工厂类。

3.典型的解耦框架。高层模块只需要知道产品的抽象类,无须关心其他实现类,满足迪米特法则、依赖倒置原则和里氏替换原则。

缺点:

1.类的个数容易过多,增加复杂度。

2.增加了系统的抽象性和理解难度。

3.抽象产品只能生产一种产品,此弊端可使用抽象工厂模式解决。

工作中的应用

敬请期待

设计原则工具箱

1.找出应用中可能需要变化的部分,把它们独立出来,不要和那些不需要变化的代码混合在一起

2.针对接口(超类型)编程而不是针对具体的实现编程

3.多用组合少用继承

4.为了交互对象之间的松耦合设计而努力

5.类应该对扩展开放,对修改关闭

6.依赖抽象,不要依赖具体类。(即不要让高层组件依赖低层组件,而且不管高层组件还是低层组件都应该依赖于抽象)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值