美文网首页
工厂方法模式

工厂方法模式

作者: 刀藏水 | 来源:发表于2020-08-22 16:14 被阅读0次

日常工作中不知道你没有碰到这种情况: 测试环境调用一个服务, 但是这个服务却不可用,导致流程进行不下去。

我经历过的做法大体有两种:

  1. 把调用这个服务的相关代码注掉。
  2. 把服务发到预发环境。

这两种方法, 如果说外行可能用点过分,毕竟很多时候,这两种方式是最实用,最容易想到的。那么是对是错就暂时不讨论了。我提供一种我使用的方法。话不多说,"talk is cheap, show me the code".

有一个功能Notification,Notification会调用一个短信服务SmsService。 你知道的,测试环境没必要真发短信吧,但是直接调用服务又没有必要,又没有测试环境的短信服务。那怎么办呢?我先看了一下短信服务的代码:

public class UglySmsService {
    // 此处省略n行代码
    public void send() {
        System.out.println("--------real sms service");
        // 此处省略n行代码
    }
    // 此处省略n行代码
}

我在想, 是不是可以先定义一个接口, 然后实现两套逻辑。一套是真正发短信功能,一套是模拟发短信功能。当在测试环境的时候,就用模拟的实现。当上线后,就用真正的短信功能? 先定义一个接口如下:

public interface SmsService {
    public void send();
}

然后是两套实现:

@Service
public class MockSmsService implements SmsService{
    @Override
    public void send() {
        System.out.println("---------mock sms service");
    }
}
@Service
public class RealSmsService implements SmsService{
    // 此处省略n行代码
    @Override
    public void send() {
        System.out.println("--------real sms service");
        // 此处省略n行代码
    }
    // 此处省略n行代码
}

代码没有重构之前, 短信服务是这样调用的:

public class UglyNotification {
    UglySmsService uglySmsService;
    public void send() {
        uglySmsService.send();
    }
}

现在我有两套短信服务的实现了,send()方法里面用哪个实现呢?我写代码的时候是不确定的,只需要运行的时候把这个服务对象注入进去就行了。所以定义了一个抽象类,代码如下:

public abstract class Notification {
    abstract SmsService createSmsService();
    public void sendSms() {
        SmsService smsService = createSmsService();
        smsService.send();
    }
}

当我在测试环境的时候,我使用Notification的测试环境的实现,当在线上的时候,我使用Notification的线上实现,代码如下:

@Service
@ConditionalOnProperty(name = "notification.env", havingValue = "test")
public class MockNotification extends Notification{
    @Resource
    SmsService mockSmsService;

    @Override
    SmsService createSmsService() {
        return mockSmsService;
    }
}
@Service
@ConditionalOnProperty(name = "notification.env", havingValue = "prod")
public class RealNotification extends Notification{
    @Resource
    SmsService realSmsService;

    @Override
    SmsService createSmsService() {
        return realSmsService;
    }
}

不知道你体会到了没有。代码的关键就在于抽象类的createSmsService()这个方法。这个方法是用来创建对象用的。它就是平常所说的工厂方法模式。在咱们的例子里面可以这样理解:我有两个短信服务,我根据不同的环境需要调用不同的短信服务。两个短信服务实现相同的接口,所以我的代码逻辑是:我只管取一个短信服务实现,至于具体是真实服务还是模拟服务由子类来决定。 测试一下

@SpringBootTest
class PawnMoveApplicationTests {

  @Resource
  Notification notification;

  @Test
  void testFactoryMethod() {
    notification.sendSms();
  }
}

当我的配置文件如下时:

notification.env=test

打印

---------mock sms service

这就实现了根据不同的配置实例化不同的短信服务。

我的这个例子,是把service当作对象来处理, 只不过这个service是没有状态的。这种情况在日常开发中非常多见。因为web开发基本都是mvc架构,而且mvc架构是基本于“贫血”模型的。

“工厂方法”模式是模板模式的一个特殊例子,也是虚拟工厂的基本组件。理解工厂方法模式的关键就是抽象类中的抽象方法。它的意义在于让子类决定生成一个什么样的对象。切记切记。让子类来决定生成什么样的对象。

文章里面的代码可以访问  代码的github地址

如果认为我写的文章不错,可以添加我的微信公众号,我会每周发一篇原创文章,和大家共同探讨编程,学习编程。


刀藏水

相关文章

  • 设计模式-3种工厂模式

    工厂模式包括:简单工厂模式,工厂方法模式,抽象工厂模式 简单工厂模式 工厂方法根据参数直接创建实例:工厂->产品 ...

  • 设计模式-工厂模式

    工厂模式概念 实例化对象,用工厂方法代替new操作。工厂模式包括工厂方法模式和抽象工厂模式。抽象工厂模式是工厂模式...

  • 设计模式-工厂方法模式

    1、工厂方法模式(Factory Method) 工厂方法模式分为三种: 普通工厂模式 多个工厂模式 静态工厂模式...

  • 设计模式 工厂模式

    工厂模式 工厂模式三大类1、简单工厂模式(静态工厂方法模式)2、工厂方法模式3、抽象工厂模式(Kit模式) 简单工...

  • python设计模式 - 工厂模式之工厂方法

    python 环境 工厂方法模式简介 工厂方法模式Factory Method,又称多态性工厂模式。在工厂方法模式...

  • 第一章2.0工厂- 基础类准备

    2.1工厂-简单工厂模式2.2工厂-工厂方法模式2.3工厂-抽象工厂模式

  • 建造模式

    包括:简单工厂、工厂方法、抽象工厂、单例模式、多例模式、建造模式、原始原型模式。 简单工厂:又名静态工厂方法模式,...

  • PHP-浅谈单例模式和工厂模式

    PHP中常用的设计模式有单例模式、工厂模式(简单工厂模式、工厂方法模式和抽象工厂方法模式)、适配模式、策略模式。 ...

  • 设计模式学习--工厂方法模式

    模式定义 工厂方法模式又称工厂模式,也叫虚拟构造器模式或者多态工厂模式,它属于类创建型模式。在工厂方法模式中,工厂...

  • 五分钟精通设计模式(三)之工厂方法模式

    工厂方法模式分为三种: 普通工厂方法模式、多个工厂方法模式、静态工厂方法模式 废话不多说,下面直奔主题,实现步骤:...

网友评论

      本文标题:工厂方法模式

      本文链接:https://www.haomeiwen.com/subject/boevjktx.html