个人博客原文
创建型模式:工厂方法 <http://www.liebrother.com/factory-method-pattern>



简介

姓名:工厂方法

英文名:Factory method Pattern

价值观:扩展是我的专属

个人介绍:

Define an interface for creating an object,but let subclasses decide which
class to instantiate.Factory Method lets a class defer instantiation to
subclasses. (定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)
(来自《设计模式之禅》)

你要的故事

还记得上一篇 单例模式 <https://mp.weixin.qq.com/s/aJSf8yESPeex78S6W0FWWw>
中的故事么?小明开着汽车去旅游、去学校、去聚会。这一次还是延续小明的故事,一个故事能讲 2 个设计模式,不容易呀。。。(每次想故事都想破脑袋,每一篇文章至少有
3 个故事从脑子里闪过,但最终留下的只有一个适合,为了就是能比较清晰简单的说明设计模式中的关键要点。)

简单工厂


小明家里以前不算很富裕,但是还是有一个不错的车库,什么汽车、摩托车、自行车啥的都放在这个车库里。小明每次要出去,都会到车库里面挑合适的车出发。比如,小明最近期末考试了,骑摩托车去学校考试,考完试之后,小明就准备去旅游,这次决定自驾游,开着自己家的小汽车去。这个场景我们用代码描述下。
public class SimpleFactoryTest { public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing(); // 小明骑摩托车去学校 IVehicle motorcycle =
GarageFactory.getVehicle("motorcycle"); xiaoMing.goToSchool(motorcycle); //
小明开汽车去旅游 IVehicle car = GarageFactory.getVehicle("car"); xiaoMing.travel(car);
} } /** * 车库 */ class GarageFactory { public static IVehicle getVehicle(String
type) { if ("car".equals(type)) { return new Car(); } else if
("motorcycle".equals(type)) { return new Motorcycle(); } throw new
IllegalArgumentException("请输入车类型"); } } /** * 交通工具 */ interface IVehicle { void
run(); } /** * 汽车 */ class Car implements IVehicle { @Override public void
run() { System.out.println("开汽车去。。。。"); } } /** * 摩托车 */ class Motorcycle
implements IVehicle { @Override public void run() {
System.out.println("骑摩托车去。。。。"); } } class XiaoMing { public void
goToSchool(IVehicle vehicle) { System.out.println("小明去学校"); vehicle.run(); }
public void travel(IVehicle vehicle) { System.out.println("小明去旅游");
vehicle.run(); } }
上面代码看懂了么? 小明家里有一个车库 GarageFactory,里面放着汽车 Car 和摩托车
Motorcycle,小明要出去的时候,就到车库选择车,通过传递参数给
GarageFactory.getVehicle(),指明要什么车,然后小明就骑着车出发了。

这个代码真正的术语叫:简单工厂模式(Simple Factory Pattern),也叫做静态工厂模式
。它是工厂方法中的一个实现方式,从字面理解就可以知道,它是最简单的工厂方法实现方式。它有一点点小缺陷,就是扩展性不够好
,在上面代码中,小明只能骑摩托车或者开汽车,如果小明要骑单车出去呢?势必得在 GarageFactory 中添加 if
是自行车的逻辑。这违反了哪条规则了?是不是那个允许扩展,拒绝修改的开闭原则
<https://mp.weixin.qq.com/s/szBP4A1TFQL1RVZvXEknRA>?

不是说简单工厂这种实现方式不好,而是扩展性不够,在平时的开发中,简单工厂模式也用得不少。在这个小明家里车不多的情况下,用一个车库也是合适的。

工厂方法


小明老爸近几年赚了不少,车迷的两父子一直买车,家里的车越来越多,这时候,他们决定多建几个车库,按车类型放置。比如,有一个汽车库,一个摩托车库。这时候小明要开汽车就去汽车库,要骑摩托车就去摩托车库。代码实现如下。
public class FactoryMethodTest { public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing(); // 小明骑摩托车去学校 VehicleGarage motorcycleGarage
= new MotorcycleGarage(); IVehicle motorcycle = motorcycleGarage.getVehicle();
xiaoMing.goToSchool(motorcycle); // 小明开汽车去旅游 VehicleGarage carGarage = new
CarGarage(); IVehicle car = carGarage.getVehicle(); xiaoMing.travel(car); } }
interface VehicleGarage { IVehicle getVehicle(); } /** * 汽车车库 */ class
CarGarage implements VehicleGarage { @Override public IVehicle getVehicle() {
return new Car(); } } /** * 摩托车车库 */ class MotorcycleGarage implements
VehicleGarage { @Override public IVehicle getVehicle() { return new
Motorcycle(); } }
上面代码重用了简单工厂实现方式的交通接口以及摩托车和汽车的实现类。代码中有 2 个车库,一个是汽车车库 CarGarage,一个是摩托车库
MotorcycleGarage。如果小明要骑自行车,只需要建一个自行车车库,完全不用去修改汽车车库或者摩托车车库,就非常符合开闭原则,扩展性大大的提高。

总结

工厂方法模式可以说在你能想到的开源框架源码中必定会使用的一个设计模式,因为开源框架很重要一点就是要有扩展性,而工厂方法模式恰恰具有可扩展性
。弄懂了工厂方法模式,以后看开源代码就很得心应手啦。

参考资料:《大话设计模式》、《Java设计模式》、《设计模式之禅》、《研磨设计模式》、《Head First 设计模式》

代码链接:Factory method Pattern
<https://github.com/1CSH1/DesignPatterns/tree/master/src/com/liebrother/designpatterns/factorymethod>

希望文章对您有所帮助,设计模式系列会持续更新,感兴趣的同学可以关注公众号 LieBrother,第一时间获取文章推送阅读,也可以一起交流,交个朋友。

公众号之设计模式系列文章
<https://mp.weixin.qq.com/mp/homepage?__biz=MzIxMzgwMTAyMg==&hid=2&sn=c97b64288d92312f57d3c8298f8d8888>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信