工厂模式应该是我们比较常用的设计模式之一,它提供了一种创建对象的最佳方式,在创建对象时不会对调用者暴露创建逻辑,调用者只需根据自己的需求获取需要的对象,做到"拿来即用"。
说人话就是,我要什么,你就得给什么。
我们用生活中常用的支付来说明工厂模式的实现逻辑。我们在用手机支付的时候都会选择支付方式,比如微信支付、支付宝支付,当然还有其他的比如微付充支付、连连支付等等。用户选择了某一种支付方式,相应的要生成支付的对象,执行支付的方法,而这里支付对象的生成,我们交给工厂去做。
首先定义一个支付的抽象类:
抽象产品类
这个类的作用是标准化支付对象,规定好支付对象可以进行的操作,那就是下单。
然后就可以具体化我们的支付对象了,这里就以微信支付和支付宝支付为例:
微信支付产品类
有了具体的支付产品类,我们就可以创建工厂进行生产了,将微信支付和支付宝支付的支付对象给创建出来:
工厂类
接下来做一个小测试,模拟下用户支付,假设用户选择了微信支付:
测试方法
可以看到最终执行了微信的下单方法。
OK,大功告成,可以下班啦!
但这真的是我们要的工厂模式吗?
假如我们需要再加一种支付方式,比如连连支付,怎么整?简单啊,再加个连连支付的产品类,工厂类里再加个if判断,返回连连支付的对象,不就OK了吗?
这样是可以实现的。但如果我们在工厂类里进行扩展的时候,一不小心留个bug在里面,有可能会导致整个工厂类都不可用了,进而连带着整个支付系统就不可用了,这样显然是不合理的。实际上,这样的工厂模式违背了一个很重要的设计原则——开闭原则。开闭原则就是说,当你在扩展程序的时候,不要改动原有代码,要实现一个热插拔的效果。
这种工厂模式实际上称为简单工厂模式,是一个管理混乱、杂乱无章的小作坊,而我们需要的,是一个井然有序、收放自如的现代化工厂。
所以,这就延伸出了另一种工厂模式——工厂方法模式。
既然在原有的工厂类上进行扩展是不合理的,那索性就把工厂类分开,一个支付一个工厂类,各自工厂类生产各自的支付对象,当需要进行扩展的时候,只需新建自己的工厂类和支付产品类,而与其他的支付方式无关,这样就实现了热插拔的效果。
于是我们的代码可以演变为,保留原有的支付抽象类和支付产品类,去掉工厂类,新建一个抽象工厂类,微信支付和支付宝支付各自实现其工厂类。
抽象工厂类
微信支付工厂类
这样就实现了工厂类的分离,微信支付工厂类负责生产微信支付的产品,支付宝支付工厂类负责生产支付宝支付的产品,所有工厂类各司其职,互不干扰。
测试一下:
这样,工厂方法模式就实现了,这其实也是我们平时用的最多的模式,平时所说工厂模式实际就是指的工厂方法模式。当然,工厂模式还有抽象工厂方法模式,这是比小作坊、小工厂更加高级的超级工厂模式,实现起来比较繁琐,平时也基本用不到,这里就不细说了。