设计模式之工厂模式(Factory)

原创 2016年11月26日 09:51:22

转载请标明出处:http://blog.csdn.net/shensky711/article/details/53348412
本文出自: 【HansChen的博客】

设计模式系列文章:
设计模式之工厂模式
设计模式之模板方法模式和策略模式

概述

根据依赖倒置原则,我们知道,我们应优先依赖抽象类而不是具体类。在应用开发过程中,有很多实体类都是非常易变的,依赖它们会带来问题,所以我们更应该依赖于抽象接口,以使我们免受大多数变化的影响。
工厂模式(Factory)允许我们只依赖于抽象接口就能创建出具体对象的实例,所以在开发中,如果具体类是高度易变的,那么该模式就非常有用。

接下来我们就通过代码举例说明什么是工厂模式

简单工厂模式

假设我们现在有个需求:把一段数据用Wi-Fi或者蓝牙发送出去。
需求很简单是吧?刷刷刷就写下了以下实现:

    private String mode; //Wi-Fi|Bluetooth

    public void onClick() {
        byte[] data = {0x00, 0x01};

        if ("Wi-Fi".equals(mode)) {
            sendDataByWiFi(data);
        } else {
            sendDataByBluetooth(data);
        }
    }

    private void sendDataByWiFi(byte[] data) {
        // send data by Wi-Fi
    }

    private void sendDataByBluetooth(byte[] data) {
        // send data by Bluetooth
    }

但是上面的代码扩展性并不高,违反了开放封闭原则。比如现在又有了个新的需求,需要用zigbee把数据发送出去,就得再新增一个sendDataByZigbee方法了,而且还得修改onClick里面的逻辑。那么比较好的方法是怎么样的呢?

定义一个数据发送器类:

/**
 * 数据发送器Sender
 *
 * @author HansChen
 */
public interface Sender {

    void sendData(byte[] data);
}

实现WiFi数据发送:

/**
 * Sender的实现类,通过Wi-Fi发送数据
 *
 * @author HansChen
 */
public class WiFiSender implements Sender {

    @Override
    public void sendData(byte[] data) {
        System.out.println("Send data by Wi-Fi");
    }
}

实现蓝牙数据发送:

/**
 * Sender的实现类,通过蓝牙发送数据
 *
 * @author HansChen
 */
public class BluetoothSender implements Sender {

    @Override
    public void sendData(byte[] data) {
        System.out.println("Send data by Bluetooth");
    }
}

这样,原来发送数据的地方就改为了:

    private String mode; //Wi-Fi|Bluetooth

    public void onClick() {
        byte[] data = {0x00, 0x01};

        Sender sender;
        if ("Wi-Fi".equals(mode)) {
            sender = new WiFiSender();
        } else {
            sender = new BluetoothSender();
        }
        sender.sendData(data);
    }

有没有觉得代码优雅了一点?但是随着发送器Sender的实现类越来越多,每增加一个实现类,就需要在onClick里面实例化相应的实现类,能不能用一个单独的类来做这个创造实例的过程呢?这就是我们讲到的工厂。我们新增一个工厂类:

/**
 * 简单工厂类
 *
 * @author HansChen
 */
public class SimpleFactory {

    public static Sender createSender(String mode) {
        switch (mode) {
            case "Wi-Fi":
                return new WiFiSender();
            case "Bluetooth":
                return new BluetoothSender();
            default:
                throw new IllegalArgumentException("illegal type: " + mode);
        }
    }
}

这样一来,怎么实例化数据发送器我们也不用管了,最终代码变为:

    private String mode; //Wi-Fi|Bluetooth

    public void onClick() {
        byte[] data = {0x00, 0x01};

        Sender sender = SimpleFactory.createSender(mode);
        sender.sendData(data);
    }

好了,到这里我们就完成了简单工厂模式的应用了,下图就是简单工厂模式的结构图:
这里写图片描述

工厂方法模式

简单工厂模式的优点在于工厂类包含了必要的判断逻辑,根据传入的参数动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是这里还是会有个问题,假设上面例子中新增了一个zigbee发送器,那么一定是需要修改简单工厂类的,也就是说,我们不但对扩展开放了,对修改也开放了,这是不好的。解决的方法是使用工厂方法模式,工厂方法模式是指定义一个用于创建对象的接口,让子类决定实例化哪一个类。下面还是通过代码来说明:

在简单工厂模式的基础上,让我们对工厂类也升级一下,首先定义一个工厂类接口:

public interface SenderFactory {

    Sender createSender();
}

然后为每一个发送器的实现类各创建一个具体的工厂方法去实现这个接口

定义WiFiSender的工厂类:

public class WiFiSenderFactory implements SenderFactory {

    @Override
    public Sender createSender() {
        return new WiFiSender();
    }
}

定义BluetoothSender的工厂类:

public class BluetoothSenderFactory implements SenderFactory {

    @Override
    public Sender createSender() {
        return new BluetoothSender();
    }
}

这样,即使有新的Sender实现类加进来,我们只需要新增相应的工厂类就行了,不需要修改原有的工厂,下图就是工厂方法模式的结构图:
这里写图片描述

客户端调用代码:

    private String mode; //Wi-Fi|Bluetooth

    public void onClick() {
        byte[] data = {0x00, 0x01};

        SenderFactory factory;
        if ("Wi-Fi".equals(mode)) {
            factory = new WiFiSenderFactory();
        } else {
            factory = new BluetoothSenderFactory();
        }
        Sender sender = factory.createSender();
        sender.sendData(data);
    }

细心的读者可能已经发现了,工厂方法模式实现时,客户端需要决定实例化哪一个工厂类,相比于简单工厂模式,客户端多了一个选择判断的问题,也就是说,工厂方法模式把简单工厂模式的内部逻辑判断移到了客户端!你想要加功能,本来是修改简单工厂类的,现在改为修改客户端。但是这样带来的好处是整个工厂和产品体系都没有“修改”的变化,只有“扩展”的变化,完全符合了开放封闭原则。

总结

简单工厂模式和工厂方法模式都封装了对象的创建,它们使得高层策略模块在创建类的实例时无需依赖于这些类的具体实现。但是两种工厂模式之间又有差异:

  • 简单工厂模式:最大的优点在于工厂类包含了必要的判断逻辑,根据客户端的条件动态地实例化相关的类。但这也是它的缺点,当扩展功能的时候,需要修改工厂方法,违反了开放封闭原则
  • 工厂方法模式:符合开放封闭原则,但这带来的代价是扩展的时候要增加相应的工厂类,增加了开发量,而且需要修改客户端代码
版权声明:本文为博主原创文章,转载请标明出处,谢谢

【java设计模式】之 工厂(Factory)模式

1.工厂模式的定义         工厂模式使用的频率非常高,我们在开发中总能见到它们的身影。其定义为:Define an interface for creating an object, but ...
  • eson_15
  • eson_15
  • 2016年04月23日 10:48
  • 13349

C++设计模式之Factory(工厂)模式

工厂模式一般是学习设计模式的第一课,它本身也是创建型模式中较为常用的一种模式. 工厂模式希望解决的是"如何高效而方便的创建当前需要的对象"的问题.当一个对象对外提供的接口稳定,而这类对象的具体实现容易...
  • markl22222
  • markl22222
  • 2013年12月01日 13:35
  • 1065

Android设计模式之工厂模式 Factory

一.概述 平时做项目跟使用第三方类库的时候经常会用到工厂模式.什么是工厂模式,简单来说就是他的字面意思.给外部批量提供相同或者不同的产品,而外部不需要关心工厂是如何创建一个复杂产品的过...
  • l2show
  • l2show
  • 2015年08月23日 16:25
  • 20083

Head First 设计模式 (四) 工厂模式(factory pattern) C++实现

  • 2013年04月03日 19:31
  • 3.54MB
  • 下载

设计模式(c++) 之 Factory(工厂模式)源码下载

  • 2015年09月24日 16:52
  • 213KB
  • 下载

C#面向对象设计模式纵横谈(3):Abstract Factory 抽象工厂模式(创建型模式) (Level 300)

  • 2008年09月13日 15:50
  • 7.78MB
  • 下载

C#面向对象设计模式纵横谈(3):Abstract Factory 抽象工厂模式(创建型模式)

  • 2009年08月20日 15:43
  • 6.93MB
  • 下载

设计模式(4)の创建型の抽象工厂模式(Abstract Factory)

概述工厂方法模式有一个问题就是,类的创建依赖工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则,所以,从设计角度考虑,有一定的问题。那么要想尽可能少的去修改”原有的工厂类”,而...
  • user11223344abc
  • user11223344abc
  • 2018年01月11日 16:47
  • 16

设计模式——工厂模式(Factory)

1. 定义 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 Product:负责定义产品的共性,实现对事物最抽象定义; Creator:抽象...
  • xiyanlgu
  • xiyanlgu
  • 2013年11月05日 17:03
  • 1129

23种设计模式之工厂模式(Factory)

使用new是最大的耦合使用反射可以解耦,但这里先不使用。 除了使用new操作符之外,还有更多制造对象的方法。而实例化这个活动不应该总是公开地进行,也会认识到初始化经常造成”耦合”问题。工厂模式:工厂方...
  • fanfan4569
  • fanfan4569
  • 2016年07月22日 16:09
  • 230
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:设计模式之工厂模式(Factory)
举报原因:
原因补充:

(最多只允许输入30个字)