本文将重点介绍几种工厂设计模式:简单工厂、工厂方法模式、抽象工厂模式和建造者模式。这几种设计模式在生产制造的流程下层层递进,可以满足不同的使用场景。在实际运用时,没有一个万能的工厂模式可以套用,要结合具体业务场景选择合适的设计模式。大部分童鞋很容易将这几种工厂模式弄混淆,所以建议大家收藏+关注,以后要用到了方便查阅。
为什么需要工厂模式?
在面向对象的世界里,世间万物皆是制造(实例化和初始化)出来的。如果只是单单构造出一两个对象,代码相对来说并不复杂,可是一旦需要构造成百上千的对象,每种对象的构造过程又不尽相同,这个时候就需要利用工厂方法进行封装,达到降低系统耦合和代码复用的目的。
在现实生活中,我们可以找到很多这样的例子。例如,想要在飞行游戏里生产一辆坦克和一架飞机,假设即使靠我自己的能力也能生产出来,那也是想当复杂的一件事情。不仅如此,如果我需要在不同的时间,不同的地点生产100辆坦克和50架飞机,我是不是就需要将生产的过程重复150次?
有经验的程序员立刻就能想到将坦克和飞机的制造过程独立成一个方法,每次生产坦克或飞机的时候调用这个方法即可,这样就达到了代码复用的目的。没错,这正是简单工厂的雏形,只不过这个生产方法是交由一个工厂类来管理。
简单工厂
我们以飞行游戏生产敌人为示例,介绍一下简单工厂的实现原理。首先我们对游戏敌军建模。坦克和飞机作为敌军肯定存在一定的共性,它们都需要一个坐标属性用来描述位置,它们还需要一个在地图上绘制的行为属性。所以我们可以给它们设计一个敌人的抽象类,如图所示。
坦克类继承敌人这个抽象父类,实现代码如图所示。
飞机类继承敌人这个抽象父类,实现代码如图所示。
通过上述代码可以看出,坦克和飞机都继承自敌人这个抽象父类,共用了父类的坐标属性,并且实现了各自的绘制方法show()。现实中的游戏角色肯定没有这么简单,这个示例只是为了让大家更好的理解简单工厂的原理。
游戏敌人的建模完成以后,就需要对游戏敌人进行实例化和初始化了。显然这个过程需要两步:
1、构造敌人时初始化坐标位置;
2、根据坐标在地图上绘制敌人。
我们在客户端里实现这部分逻辑,如图所示。
客户端的代码非常简单,我们生产了一架飞机和一辆坦克,它们的横坐标是随机的,纵坐标是0,表示敌人登场亮相在地图的最上面。
看出来有什么问题了吗?对,前面我们已经提到了,生产一个敌人无所谓,但是如果要生产很多的敌人,为了代码的复用,我们可以将生产过程放到一个方法里,这个方法用一个工厂类来管理,通过传递敌人的类型返回敌人对象,这就是简单工厂。
有了简单工厂类,我们在客户端里的实现逻辑就可以省去不少重复代码。