前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式实战-工厂模式,别具匠心

设计模式实战-工厂模式,别具匠心

作者头像
架构师修炼
发布2020-07-20 11:14:11
5110
发布2020-07-20 11:14:11
举报
文章被收录于专栏:架构师修炼架构师修炼

工厂模式,是设计模式中最为常见的模式之一。属于创建型模式,提供创建对象的最佳方式。

工厂模式,顾名思义,一个模型,用来大规模的生产同类产品。该模式将对象的具体实例过程抽象化,并不关心具体的创建过程。通常,工厂模式被用来定义一个对象模型,之后,便可快速规模化实例化对象。

简单工厂模式的实质:一个工厂类根据传入的参数,动态决定应该创建哪一类产品类(这些产品类均继承自一个父类或接口)实例。

1、模拟场景

本来创建对象用 new 就行了,为什么要用函数或类将 new 的过程封装起来呢?

这里,我们引入两个角色,一个是类的设计者,一个是类的使用者。类的使用者只关心 “这个对象做这事”、“那个对象做那件事”,而不关心 “这件事如何去做?”,通常,类的设计者才会去关心 “如何去做”。

举个栗子,类的设计者设计了 “阿猫”、“阿狗” 两个类,类的使用者需要创建 “阿猫 1”、“阿狗 2” 两个对象,如果不使用工厂模式,类的使用者就需要明确知道 “阿猫”、“阿狗” 两个类,这无疑增加了类使用者的负担。使用工厂来代替创建这两对象,权责分开,比方说,这些动物都有 “吃东西” 的行为,这时,“吃东西” 具体行为是什么样子,这是类的设计者关心的,而何时进行该行为,是类的使用者关心的。

再比如,我们经常使用的数据库中间件,我们无需关心具体的底层实现类,只需将用户名密码等连接信息传过去,就会直接获取到相应的数据库连接实例,这个角度,就可以将数据库中间件看作一个大的工厂。

优点:

  1. 一个调用者想创建某个对象,只需知道其名称即可
  2. 屏蔽具体行为实现,调用者只需关心产品接口,减轻调用者负担
  3. 拓展性高,如果想增加一个产品类,只需拓展一个工厂类即可

2、具体分类

一般来说,工厂模式分为三种:普通简单工厂模式、多方法简单工厂、静态方法简单工厂。这三种模式从上到下逐步抽象,并且根据一般性。

2.1 普通简单工厂

就是建立一个具体工厂类,对实现了同一接口的一些类进行实例的创建,首先看下 uml 类图(这里以发送短信、邮件、快递为例):

首先,创建一个三者共有的接口:

public interface Sender {
    public void Send();
}

然后,创建实现类:

public class EmailSender implements Sender{
    @Override
    public void Send() {
        System.out.println("发送邮件");
    }
}
public class SmsSender implements Sender{
    @Override
    public void Send() {
        System.out.println("发送短信");
    }
}

public class ExpressSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送快递");
    }
}

再然后,我们创建一个工厂类来产出这几种 “产品”:

public class SendFactory {
    public Sender produce(String type) {
        if (type == null) {
            return null;
        } else if ("email".equalsIgnoreCase(type)) {
            return new EmailSender();
        } else if ("sms".equalsIgnoreCase(type)) {
            return new SmsSender();
        } else if ("express".equalsIgnoreCase(type)) {
            return new ExpressSender();
        } else {
            return null;
        }
    }
}

接下来,我们试着调用下测试:

public class Main {

    public static void main(String[] args) {
        SendFactory sendFactory = new SendFactory();
        Sender senderSms = sendFactory.produce("sms");
        senderSms.Send(); // 发送短信

        Sender senderEmail = sendFactory.produce("email");
        senderEmail.Send(); // 发送邮件

        Sender senderExpress = sendFactory.produce("express");
        senderExpress.Send(); // 发送快递
    }
}

2.2 多方法简单工厂

多方法简单工厂是在前者的基础上该进来的,普通工厂方法在使用时,如果 type 类型传递错误则不能正确创建对象,多方法直接将 produce 中的逻辑展开到具体的方法中,从而避免该问题。接下来看下我们的改进:

针对上面代码,我们只需调整 SendFactory 类即可:

public class SendFactory {
    public Sender produceSms(){
        return new SmsSender();
    }

    public Sender produceEmail(){
        return new EmailSender();
    }

    public Sender produceExpress() {
        return new ExpressSender();
    }
}

接下来,我们进行如下简单测试:

public class Main {

    public static void main(String[] args) {
        SendFactory sendFactory = new SendFactory();
        Sender senderEmail = sendFactory.produceEmail();
        senderEmail.Send(); // 发送邮件

        Sender senderSms = sendFactory.produceSms();
        senderSms.Send(); // 发送短信

        Sender senderExpress = sendFactory.produceExpress();
        senderExpress.Send(); // 发送快递
    }
}

2.3 静态方法简单工厂

普通工厂模式和多方法工厂模式有一个弊端,就是需要频繁的实例化工厂类,一般我们会将 “多方法” 设置为静态的,从而避免类的频繁实例化,拿来即用。

这里我们直接看修改后的 SendFactory 类:

public class Main {

    public static void main(String[] args) {
        //SendFactory sendFactory = new SendFactory();
        Sender senderEmail = SendFactory.produceEmail();
        senderEmail.Send(); // 发送邮件

        Sender senderSms = SendFactory.produceSms();
        senderSms.Send(); // 发送短信

        Sender senderExpress = SendFactory.produceExpress();
        senderExpress.Send(); // 发送快递
    }
}

3、简单工厂的延申 — 工厂方法模式

上面介绍的简单工厂模式有个比较明显的弊端:工厂类集中了所有实例的创建逻辑,明显违背高内聚的责任分配原则,违背了闭包规则。

而工厂方法模式则是对该问题的进一步延伸解决,差异就是将原先存在于一个工厂类中的逻辑抽调出来,创建一个接口和多个工厂类。这样,一旦功能有新增,比如说我们要加一个 “发送导弹” 的功能,只需要加一个 “导弹发送工厂类”,该类实现 produce 接口返回实例化的 “导弹发送类”,再在 “导弹发送类” 中,实现具体的发送逻辑即可,无需修改之前的业务代码,拓展性较好。

首先,我们还是创建一个 Sender 接口:

public interface Sender {
    public void Send();
}

然后我们创建几个具体的实现类:

public class SmsSender implements Sender{
    @Override
    public void Send() {
        System.out.println("发送短信");
    }
}
public class ExpressSender implements Sender {
    @Override
    public void Send() {
        System.out.println("发送快递");
    }
}
public class EmailSender implements Sender{
    @Override
    public void Send() {
        System.out.println("发送邮件");
    }
}

然后,我们统一一下工厂类的接口行为:

public interface Provider {
    public Sender produce();
}

继续,定义几个工厂实现上面这种 “行为约束”:

public class ExpressSendFactory implements Provider {
    @Override
    public Sender produce() {
        return new ExpressSender();
    }
}
public class EmailSendFactory implements Provider{
    @Override
    public Sender produce() {
        return new EmailSender();
    }
}
public class SmsSendFactory implements Provider {
    @Override
    public Sender produce() {
        return new SmsSender();
    }
}

测试类:

public class Main {

    public static void main(String[] args) {
        Provider providerSms = new SmsSendFactory();
        Sender senderSms = providerSms.produce();
        senderSms.Send(); // 发送短信

        Provider providerEmail = new EmailSendFactory();
        Sender senderEmail = providerEmail.produce();
        senderEmail.Send(); // 发送邮件

        Provider providerExpress = new ExpressSendFactory();
        Sender senderExpress = providerExpress.produce();
        senderExpress.Send(); // 发送快递
    }
}

4、总结

工厂方法模式中,核心的工厂类(这里为 Provider 接口)不再负责所有产品的创建,而是将具体创建的工作交给子类去做,该核心类仅扮演抽象工厂的角色,负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应该被实例化的细节,拓展性较简单工厂模式提升明显。

关于架构师修炼

本号旨在分享一线互联网各种技术架构解决方案,分布式以及高并发等相关专题,同时会将作者的学习总结进行整理并分享。

更多技术专题,敬请期待

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师修炼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、模拟场景
  • 2、具体分类
    • 2.1 普通简单工厂
      • 2.2 多方法简单工厂
        • 2.3 静态方法简单工厂
        • 3、简单工厂的延申 — 工厂方法模式
        • 4、总结
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档