一文搞懂设计模式--工厂方法模式

4. 工厂方法(Factory Method)模式

Hi,大家好呀。昨天发的文章迟迟没有通过审核,今天一天都在和审核组斗智斗勇,问题是违规的内容在文章中压根就没有(QAQ)。唉,虽然经历了不少挫折但是生活还要继续对吧o(╥﹏╥)o。今天的主题是工厂方法模式,还是老样子,让我们先构建一个应用场景:

场景定义

今天一位尊敬的甲方来到你的公司,准备请你们帮助定制开发一个软件。产品经理几乎快说断了三寸不烂之舌,甲方代表终于满意的点点头,大手一挥在合同上写下大名。陪着甲方走出公司的大门后,产品经理终于有机会连灌了一瓶水下肚,紧接着就开始了对你的摧残。甲方的要求是这样:

今天的甲方是一个实业家,手下掌握有大量的工厂,生产众多不同的产品。但是随着工厂规模的扩大,生产过程中的环节为管理产品带来了许多问题,他希望你们能够开发一个软件帮助他管理产品生产的过程。你们经过详细的调研,了解到一个产品在工厂中通常会经历以下三个阶段

  1. 为产品选择合适的模具

  2. 采用不同的工艺生产产品

  3. 对产品进行质量检测

  4. 试用产品

其工厂的代表产品是小葱手机和尖叫鸡,于是你们打算以此为模板率先开发一个demo。

产品经理将这项艰巨的工作交给了你,本着能摸鱼绝对不划水的态度,你从手下的一众小弟中挑出一个浓眉大眼,看起来温顺无害的小伙子。对他进行了一套画饼充饥的连招后,成功让他斗志满满的决定晚上加班搞定这个需求,你满意的点点头,看看墙上的钟,估摸着到点了,晚上女神还等着你去帮他拎包呢,于是迈着六亲不认的步伐麻溜的润了。

第二天来到公司,小伙子盯着黑眼圈站在你的办公桌前,一脸兴奋告诉你他已经完成了这个需求,正等着你毫无保留的夸奖。你坐在椅子上看着小伙提交上来的代码,感觉脑仁一阵突突的疼,不断告诉自己要冷静,谁还没有年轻过,年轻人都会犯错。

简单的实现

小伙提交上来的代码是这样的

大葱手机工厂

public class PhoneFactory {
    public void selectMold(){
        System.out.println("选择大葱手机模具");
    }
    public void produce(){
        System.out.println("生产大葱手机");
    }
    public void checkout(){
        System.out.println("使用大葱手机拍核桃,检查质量是否合格");
    }
}

大葱手机

public class Phone {
    public void  use(){
        System.out.println("欢迎使用大葱手机");
    }
}

尖叫鸡工厂

public class ScreamingChickenFactory {
    public void selectMold(){
        System.out.println("选择尖叫鸡橡胶模具");
    }
    public void produce(){
        System.out.println("生产尖叫鸡");
    }
    public void checkout(){
        System.out.println("使劲捏捏尖叫鸡,看看会不会尖叫");
    }
}

尖叫鸡

public class ScreamingChicken {
    public void use(){
        System.out.println("啊啊啊啊啊啊~");
    }
}

以及调用他们的主类

public class Main {
    public static void main(String[] args) {
        // 大葱手机工厂
        PhoneFactory phoneFactory = new PhoneFactory();
        Phone phone = phoneFactory.create();
        phone.use();

        System.out.println("********************************");

        //尖叫鸡工厂
        ScreamingChickenFactory screamingChickenFactory = new ScreamingChickenFactory();
        ScreamingChicken screamingChicken = screamingChickenFactory.create();
        screamingChicken.use();
    }
}

程序输出:

选择大葱手机模具

生产大葱手机

使用大葱手机拍核桃,检查质量是否合格

欢迎使用大葱手机

********************************

选择尖叫鸡橡胶模具

生产尖叫鸡

使劲捏捏尖叫鸡,看看会不会尖叫

啊啊啊啊啊啊~

📌大家不要太过在意业务的合理性,构建一个背景的目的只是为了可以让我们更好的理解知识,而不是被业务的细节所迷惑

你伸手揉了揉太阳穴问道,我们这只是用这两个产品做个demo,那客户那些其他产品的工厂怎么办?

小伙子一脸无辜的说:那我在加班加点都写上去就好啦。

你感觉你的血压蹭的往上涨了一截,年轻人能熬,你codereview可熬不住。沉默了一会,你长长叹了一口气,决定将你的独门绝技传授一部分给这个年轻的小伙子。

什么是工厂方法模式

在模板方法模式中,我们在父类中规定处理的流程,在子类中实现具体的处理(什么?不知道什么是模板方法模式,快来这篇文章看看)。如果我们将该模式用于生成实例,它就演变为工厂方法模式。在工厂方法模式中,由父类决定实例的生成方式,但并不决定具体要生成的类。通过将具体的生成处理交给子类负责,这样就可以将生成实例的框架和负责生成实例的类解耦。

让我们看看用工厂方法模式如何实现上面的需求

工厂方法模式的具体实现

抽象工厂的实现

public abstract class Factory {
    /**
     * 抽象的选择模具过程
     */
    public abstract void selectMold();

    /**
     * 抽象的生产过程
     * @return 产品
     */
    public abstract Product produce();

    /**
     * 抽象的测试过程
     */
    public abstract void checkout();

    /**
     * 定义规定好的生产流程
     * @return 产品
     */
    public Product create(){
        this.selectMold();
        Product product = this.produce();
        this.checkout();
        return product;
    }
}

大葱手机工厂的实现

public class PhoneFactory extends Factory{
    /**
     * 实现具体的选择模具动作
     */
    public void selectMold(){
        System.out.println("选择大葱手机模具");
    }

    /**
     * 实现具体的生产产品动作
     * @return 大葱手机
     */
    public Product produce(){
        System.out.println("生产大葱手机");
        return new Phone();
    }

    /**
     * 实现具体的质量检测动作
     */
    public void checkout(){
        System.out.println("使用大葱手机拍核桃,检查质量是否合格");
    }
}

尖叫鸡工厂的实现

public class ScreamingChickenFactory extends Factory{
    /**
     * 具体的选择模具动作
     */
    public void selectMold(){
        System.out.println("选择尖叫鸡橡胶模具");
    }

    /**
     * 具体的生产尖叫鸡
     * @return 尖叫鸡
     */
    public Product produce(){
        System.out.println("生产尖叫鸡");
        return new ScreamingChicken();
    }
    /**
     * 具体的质量检测动作
     */
    public void checkout(){
        System.out.println("使劲捏捏尖叫鸡,看看会不会尖叫");
    }
}

抽象产品的实现

public abstract class Product {
    /**
     * 抽象的使用产品动作
     */
    public abstract void use();
}

大葱手机的实现

public class Phone extends Product{
    /**
     * 具体的使用手机
     */
    public void  use(){
        System.out.println("欢迎使用大葱手机");
    }
}

尖叫鸡的实现

public class ScreamingChicken extends Product {
    /**
     * 具体的使用尖叫鸡
     */
    public void use(){
        System.out.println("啊啊啊啊啊啊~");
    }
}

调用他们的主类

public class Main {
    public static void main(String[] args) {
        // 大葱手机工厂
        Factory factory = new PhoneFactory();
        Product product = factory.create();
        product.use();

        System.out.println("********************************");

        //尖叫鸡工厂
        // 只需要在这里进行修改就可以改变产品
        factory = new ScreamingChickenFactory();
        product = factory.create();
        product.use();
    }
}

程序运行结果:

选择大葱手机模具

生产大葱手机

使用大葱手机拍核桃,检查质量是否合格

欢迎使用大葱手机

********************************

选择尖叫鸡橡胶模具

生产尖叫鸡

使劲捏捏尖叫鸡,看看会不会尖叫

啊啊啊啊啊啊~

通过对比,很容易可以得出,通过工厂方法模式,接下来如果还有其他的产品需要加入,我们只需要通过对类进行简单的拓展,就可以适配新的产品。

工厂方法模式中出现的角色

让我么从整体上来看看工厂方法模式的类图

Creator(创建者)

创建者属于框架的一方,他负责创建Product这个抽象类,但是具体的处理由其子类来决定。在上文的例子中Factory担任创建者角色。创建者角色并不知道要生成哪种实例,只需要调用生成实例的方法就可以生成Product实例。

Product(产品)

产品角色同样属于框架的一方,是一个抽象类。在这个角色中只定义了产品需要实现的接口,而具体的处理则交给其子类。

ConcreteCreator(具体的创建者)

ConcreteProduct角色属于具体的加工方,他实现了父类Creator中的方法,决定了具体生产的产品。上文的例子中PhoneFactory和ScreamingChickenFactory都扮演了这个角色。

ConcreteProduct(具体的产品)

ConcreteProduct属于具体的加工方,他负责生成具体的产品。上文的例子中Phone和ScreamingChicken都扮演了这个角色。

拓展思路

通过上面的例子,如果大家对模板模式有所了解的话,应该可以看出工厂模式实际上与模板模式极其类似,都是通过父类定义标准和固定的处理流程,而具体的实现方法则交给子类实现,这样的模式可以极大的增加代码的灵活度和拓展性,希望大家能够掌握其中的精髓。

当然,这两个模式也有自己的缺点,其中之一就是如果开发者没有理解在类中定义的固定流程(通常在实际开发中,业务逻辑会比上文例子中复杂数十倍),这就会导致开发者在开发其具体子类时遇到极大困难。因此我们在使用这些模式时,一定要向维护这些类的开发者准确传达这些设计模式的目的。否则将会适得其反。

往期文章

一文搞懂设计模式–外传

一文搞懂设计模式–迭代器模式

文搞懂设计模式–适配器模式

一文搞懂设计模式–模板模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
责任链设计模式是一种行为型设计模式,用于将请求的发送者和接收者解耦,使多个对象都有机会处理该请求。该模式将这些对象串成链,并沿着这条链传递请求,直到有一个对象能够处理它为止。 责任链模式的核心是定义一个处理请求的抽象类或接口,然后让多个具体的处理者对象继承或实现这个类/接口。每个具体的处理者对象都包含一个对下一个处理者对象的引用,形成一个链式结构。 当一个请求进入责任链时,责任链中的每个处理者都有机会处理该请求。如果可以处理请求,则进行处理;如果不能处理,则将请求传递给下一个处理者,直到有一个处理者能够处理它。 责任链模式的关键点是要找到合适的处理者顺序和条件。通常情况下,责任链模式适用于以下情况: 1. 有多个对象可以处理同一类型的请求,但具体由哪个对象来处理由运行时决定。 2. 不明确请求的接收者,希望请求在一个对象链中流动,直到被处理。 3. 需要动态地指定可以处理请求的对象集合。 使用责任链模式可以实现请求发送者和接收者的解耦,增加代码的灵活性和可扩展性。但同时也需要注意责任链的长度和效率问题,避免责任链过长或造成性能问题。 总结一下,责任链设计模式是一种将请求发送者和接收者解耦的设计模式,通过将多个处理者对象串成链,沿着这条链传递请求,直到有一个处理者能够处理它。这样可以增加代码的灵活性和可扩展性,适用于有多个对象可以处理同一类型请求的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值