设计模式——工厂模式

工厂模式

工厂模式,对于大部分的开发者来讲,可能并不陌生,但是可能并非所有人都能完全理解,尤其是对于初学者。有的初学者经常会问:

工厂模式有什么用?有什么好处?什么时候用工厂模式?

网络上也有很多解答,诸如:可以更好的封装、模块化、还有的书上写着在生成复杂对象的地方,可以使用工厂模式。那么如何衡量一个对象的复杂的?这些解释都是对的,但是对于一个初学者并不好理解。

对于初学者,最大的疑惑可能就在于:通过工厂create出来的对象和new出来的对象相比,优势在哪里?直接new不就好了吗,还要写个工厂类这么麻烦?

笔者也是一直处于学习过程,梳理了一下工厂模式的使用场景和解决的痛点,通俗的聊一聊,如有错误,欢迎指正!


抛开前面抽象的定义,举一个通俗的例子,带你自然而然的应用上工厂设计模式。

某团队有如下两位开发人员:

  • 移动端 : 小张
  • 算法 : 小李

小张负责终端应用的开发,小李根据具体的业务逻辑写一些算法,封装成SDK提供给小张使用。

某天,产品提出了需求,需要开发某功能,算法小李根据需求,封装了一个类,提供了一个1.0版本的SDK给终端小张使用。具体如下

public class FunctionA{

    public void method(){
        // 业务逻辑
    }
}

小张可以在程序里直接调用方法而不用管小李是如何实现的

FunctionA functionA = new FunctionA();
functionA.method();

两人各司其职,合作非常愉快。如果你也觉得,恩,他们配合的不错,那么你可以继续往下看。

直到有一天,产品又提出了新的需求,以前的算法逻辑不用了,有了新的逻辑。

算法小李最开始想到的就是,OK,改一下FunctionAmethod()方法,改为新的。但是小李一想,如果某一天万恶的产品又要改回去怎么办?想想不行,之前的算法不能删,于是乎,算法小李又重新定义了一个类,实现了第二套业务逻辑,生成了1.1版本的SDK给终端小张使用,果然高明。

public class FunctionB{

    public void method(){
        // 新的业务逻辑
    }
}

终端小张收到算法小李给的SDK以后发现,根据需求,以前的FunctionA不能再用了,于是乎,终端小张也开始改程序,使用FunctionB

FunctionB functionB = new FunctionB();
functionB.method();

终端小张开始有点不爽,你改你的算法,和我有什么关系?增加我的工作量!
(试想一下,如果你使用了某第三方SDK,SDK每次更新,你在本地都要改代码,是不是得疯掉?)

产品又来了,改改改……
改了好多次,小张和小李打了起来……

算法小李应该怎样做,可以避免这种情况?这里就可以使用到工厂方法。

算法FunctionA和算法FunctionB都是为了实现同一个功能,只不过实现过程不一样。

终端小张想要的是:

你改你的算法,你改完算法,我可以替换新的SDK,但是不要影响到我本地的程序。

我只要调用function.method();就好了。
我不管你function是算法A还是算法B。

那么,这里小张想要的function就涉及到了Java的多态了,它即可能是FunctionA也可能是FunctionB

算法小李就可以这样改,定义一个抽象的Function,有一个抽象的method()方法,然后让算法FunctionA和算法FunctionB都继承Function,分别实现method()方法。

像这样

Function

public abstract class Function {

    public abstract void method();
}

FunctionA

public class FunctionA extends Function {

    @Override
    public void method() {
        // 算法A的实现
    }
}

FunctionB

public class FunctionB extends Function {

    @Override
    public void method() {
        // 算法B的实现
    }
}

然后再提供一个工厂类,可以返回一个多态的Function对象

public class FunctionFactory {

    public static Function createFunction() {
        return new FunctionB();
    }
}

这样一来,终端小张爽了,可以通过工厂获取Function

Function function = FunctionFactory.createFunction();
function.method();

以后算法不管怎样改,他都不需要再担心,如果产品再想改算法,算法小李只需要再定义一个FunctionC,在createFunction方法里返回即可。

这也体现了为什么说工厂模式是依赖于抽象架构的,他们都有属于一类事物,都有相同的方法,只是实现不同,由此可见,通过工厂模式,可以实现解耦,对于算法小李,还有一定的可扩展性

又有一天,产品又来新需求了,希望用户可以自己选择使用哪种逻辑算法。

终端小张希望可以提供相应接口,对应提供不同的逻辑。

算法小李首先想到的就是再多写几个create方法,诸如createFunctionA(),createFunctionB()……
虽然不是不行,但是假如你有成百上千套算法,难道要写成百上千个create方法么,这显然是码农的做法,作为工程师,我想只用一个方法,指哪打哪,要啥给啥!这就用到了反射。

可以这样实现

FuncFactory

public abstract class FuncFactory {

    public abstract <T extends Function> T createFunction(Class<T> clz);
}

FunctionFactory

public class FunctionFactory extends FuncFactory {
    @Override
    public <T extends Function> T createFunction(Class<T> clz) {
        Function function = null;
        try {
            function = (Function) Class.forName(clz.getName()).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) function;
    }
}

这样一来,终端小张就可以尽情玩耍了,
想用A算法,就传一个FunctionA

FuncFactory factory = new FunctionFactory();
Function function = factory. createFunction(FunctionA.class);

想用算法B,就传一个FunctionB

FuncFactory factory = new FunctionFactory();
Function function = factory. createFunction(FunctionB.class);

这里用到了抽象工厂类FuncFactory,同样也是为了方便扩展,现在小张和小李只用到了一种逻辑,可有可无,如果以后还有多种逻辑要实现,可以在抽象工厂里添加对应的create方法,方便扩展。

简单的理解到这里,欢迎指正!

上一篇:“好朋友越来越少,好朋友越来越好”


下一篇:阿里的开源思想:与世界讨论中国的互联网技术与场景