工厂模式

设计模式

Posted by ChaserSheng on September 28, 2017

1.概述

讲工厂模式之前我们先来讲一下我们项目中可能存在的一个问题。大家的项目中使用的缓存,不管是官方提供的SharePreference还是File存储、数据库、还是基于这些封装后的方案,在项目的使用中我们有时候没有考虑到后期应用版本升级迭代,在需要缓存数据到本地的地方我们可能这样写,以我目前使用的File缓存的开源方案ACache为例子:

最基本的用法,没有任何封装,最原始的配方

ACache aCache = ACache.get(getActivity());
aCache.put(CacheKey.SHOW_FLAG, "1");
aCache.getAsString(CacheKey.SHOW_FLAG);

开始用着还好,但是时间长了会遇到一个尴尬的情况:我们的产品越来越大,要求页越来越高,存储方案可能会细分出来,比如我们想替换成SharePreference的方案,数据库方案,像上面的那种写法,你得全局搜索然后一遍遍的改,这也太烦了,一点也不优雅。软件工程里面有个说法,如果遇到不能解决的问题,加个中间层就好了。

有没有好的方式解决这个问题呢?这就是工厂模式。

多说一句我对设计模式的理解:其实设计模式就是大家在编码过程中积累的一种经验,说到底是一个为了解决代码问题的模版。大家在相关的场景下照着这个模版做就能写出看起来还不错代码来。

工厂模式分为三种,从复杂的度、扩展性上分为:简单工厂模式、工厂方法模式、抽象工厂模式。

简单工厂模式

public class AppIOFactory implements Factory {
    public static final String PREFERENCES = "1";
    public static final String MEMERY = "2";
    public static final String DISK = "3";

    @Override
    public IOHandler createIOHandler(String type) {
        switch (type){
            case PREFERENCES:
                return new PreferenceHandler();
                break;
            case MEMERY:
                return new MemeryHandler();
                break;
            case DISK:
                return new DiskHandler();
                break;
            default:
                return new PreferenceHandler();
                break;
        }
    }
}

使用方法

AppIOFactory ioFactory = new AppIOFactory();
IOHandler ioHandler = ioFactory.createIOHandler(AppIOFactory.DISK);
ioHandler.put("name","王");
String name = ioHandler.get("name");

总结一下,我们这里不是在需要缓存的地方就new一个某种缓存模式的对象,而是通过AppIOFactory去统一的管理。

工厂方法模式

上面我们注意到AppIOFactory掌管了具体的缓存类的创建,实际使用中可能还有其它的功能,我们一般把这种类叫做“上帝类”,怎么样可以减轻这个“上帝类”的负担呢,这就是工厂方法模式。代码我这里就不给出了,其实就是为每种缓存方式创建一个IOFactory继承Factory,这个IOFactory只负责某个缓存类的创建。其它的和简单工厂模式一样。

工厂方法模式的使用

DiskIOFactory diskIOFactory = new DiskIOFactory();
IOHandler ioHandler = diskIOFactory.createIOHandler();
ioHandler.save("name","wang");
DiskIOFactory diskIOFactory = new DiskIOFactory();
IOHandler ioHandler = diskIOFactory.createIOHandler();
String userName = ioHandler.getString("name");

好处显而易见,一个工厂负责一个对象的创建,类更轻量级了。但是问题页随之而来,工厂类变多了,这个时候我们的终极版本来了,就是抽象工厂模式。

抽象工厂模式

要解决简单工厂模式和工厂方法模式造成的痛点,其实我们结合一下他们的思想

public interface Factory {
    void put(String key,String value);
    String get(String key);
}
public class DiskFactory implements Factory {

    @Override
    public void put(String key, String value) {

    }

    @Override
    public String get(String key) {
        return null;
    }
}
public interface IOFactory {
    Factory createMemoryFactory();
    Factory createDiskFactory();
    Factory createPreferenceFactory();
}
public class AppIOFactory implements IOFactory {

    @Override
    public Factory createMemoryFactory() {
        return new MemoryFactory();
    }

    @Override
    public Factory createDiskFactory() {
        return new DiskFactory();
    }

    @Override
    public Factory createPreferenceFactory() {
        return new PreferenceFactory();
    }
}

使用

Factory factory = new AppIOFactory();
factory.createDiskFactory().put("name","wang");
String name = factory.createDiskFactory().get("name");

总结:其实三种工厂方法模式的区分并没有那么严格,有时候你写着写着就会发现自己本来要写工厂方法模式然后写的是抽象工厂模式,平时在自己的项目中遇到比较复杂的地方想解耦的话,先想一想有没有什么设计模式思想可以借鉴,这样就可以写出优雅的代码了。