小more设计模式———简单工厂模式

来源:互联网 发布:淘宝双11如何抢购 编辑:程序博客网 时间:2024/04/29 12:40
1、场景
小more刚毕业,进入一家IT公司。经过一段时间的项目熟悉之后,一天老大交给他一个开发任务。具体要求:要求小more实现一个打印日志的log功能。同时提供一个接口给公司其他业务模块使用。小more经过一段时间的构思,尽可能的考虑到边界条件等因数之后。写出如下代码:
首先实现了一个接口:
/** * 日志输出接口 * Created by morethink on 2017/12/15. */public interface LogHelper {    void printLog();}
然后是一个实现类:
/** * 日志接口实现类 * Created by morethink on 2017/12/15. */public class LogHelperImpl implements LogHelper {    @Override    public void printLog() {        System.out.println("log is printing...");    }}
最后调用测试:
/** * 调用测试 * Created by morethink on 2017/12/15. */public class Run {    public static void main(String[] args){        LogHelper log = new LogHelperImpl();        log.printLog();    }}
输出如下:

然后小more就把自己的代码提交给老大,等待审核。。。。。(结果大家应该猜得到)
我们总结一下小more的代码有什么问题
(1)我们发现了在客户端调用日志打印的功能,不但知道接口是LogHelper,而且还知道接口的实现。接口的思想就是“封装隔离”,这样做违背人家接口提倡的做法。正确的做法应该是隔离客户端和接口的具体实现类。
2、解决方案
采用简单工厂来对付这种场景,虽然简单,但是却很常见。
(1)简单工厂的定义:
提供一个创建对象实例的功能,无需关心其具体实现。被创建实例的类型可以是接口、抽象类,也可以是具体的类。
(2)简单工厂的结构
说明:客户端client主要依靠工厂Factory来获取interface接口。ImplA和ImplB是接口的2个实现。
所以小more的问题我们可以使用简单工厂来实现。需要创建一个工厂类来负责产生接口。
/** * 工厂类 * Created by morethink on 2017/12/17. */public class Factory {    public static LogHelper createLogHelper(){        return new LogHelperImpl();    }}
客户端使用工厂如下:
/** * 调用测试 * Created by morethink on 2017/12/15. */public class Run {    public static void main(String[] args){        LogHelper log = Factory.createLogHelper();        log.printLog();    }}
所以简单工厂能够帮助我们真正的面向接口编程。比如以前小more的做法。只是用到了多态的部分功能,最重要的“封装隔离”没有体现出来。
3、模式分析
(1)职责:简单工厂只是负责接口的选择,它并不会去实现接口,选择合适的实现类来创建接口是它主要的职责
(2)创建对象的范围:
虽然简单工厂什么都可以创建,但是对于简单工厂可创建的对象范围。不应该太大。应该控制在一个独立的组建级别或则一个模块级别。不然的话,什么都可创建,有点大杂烩的感觉。
(3)命名建议
  • 类名建议:模块名称 + Factory,比如用户模块的工厂——UserFactory
  • 方法名称:get + 接口名称或者create + 接口名称

4、拓展
小more通过这次学会了工厂方法,觉得也不过如此。有一天,老大觉得小more写的日志工厂的功能不能很好的满足业务需求了。要求小more在增加一个日志打包功能。这次小more认真的思考了一下。小more认为简单的实现方式就是我在原来的代码中加一个判断。判断如果是需要调用打印服务,我给你提供打印服务。需要打包服务。我给你提供一个打包服务,是可以满足需求的。但是,如果用户在增加一个新需求,我还需要去修改代码。而且时间久了,维护成本很高。有没有一种更加简单的方式呢?小more想到了通过配置的方式,来满足用户新增的需求。当用户有一个新的需求。那么我只需要配置一个bean,代码不用修改,就可以满足。小more整理代码如下:
配置文件如下:
ImplClass=com.factory.LogZip
此时的工厂类实现如下:
/** * 工厂类 * Created by morethink on 2017/12/17. */public class Factory {    public static LogHelper createLogHelper(){        Properties properties = new Properties();        InputStream in = null;        try {            in = Factory.class.getResourceAsStream("app.properties");            properties.load(in);        } catch (IOException e) {            System.out.println("装载配置文件出错,堆栈信息如下:");            e.printStackTrace();        }finally {            try {                in.close();            } catch (IOException e) {                e.printStackTrace();            }        }        //反射创建        LogHelper logHelper = null;        try {            logHelper = (LogHelper)Class.forName(properties.getProperty("ImplClass")).newInstance();        } catch (Exception e) {            e.printStackTrace();        }        return logHelper;    }}
这样就可以实现一定的灵活性,当然这种处理方式不是太好。只是给各位拓展一下思路而已。

2017-12-17
写于周日加班中。。。。。



原创粉丝点击