抽象工厂模式是创建型模式之一。创建型模式有工厂模式(抽象工厂、工厂方法)、生成器模式、单体模式、原型模式四种。下面我来简单分析一下抽象工厂模式。
抽象工厂模式的定义是创建一个提供一系列相关或相互依赖对象的接口,而无需指定它们具体的类。所有的创建型模式有一个特点,我们不关心工厂生产出来的具体对象的类型,我们会将其具体的类与工厂分离开来。这么说的话,很抽象难懂,下面是一个关于星际争霸的例子。
在游戏星际争霸中,人族的兵营可以生产两种兵:机枪兵和火焰兵,机枪兵能够用机枪攻击,火焰兵能够用火焰枪来攻击。我们需要构建一个兵营,使得能够生产这两种兵,并且他们都有着自己的攻击方法。
Java代码如下:
interface SoldierFactory{
Soldier ProduceMarine();
Soldier ProduceFirebat();
}
interface Soldier{
void attack();
}
class Marine implements Soldier{
public void attack(){
System.out.println("机枪兵用机枪扫射");
}
}
class Firebat implements Soldier{
public void attack(){
System.out.println("火焰兵使用喷火枪进行攻击");
}
}
class Barracks implements SoldierFactory{
public Soldier ProduceMarine(){
System.out.println("生成了一个机枪兵");
return new Marine();
}
public Soldier ProduceFirebat(){
System.out.println("生成了一个火枪兵");
return new Firebat();
}
}
class Demo
{
public static void main(String[] args) {
Barracks myBarrack = new Barracks();
Soldier marine = myBarrack.ProduceMarine();
Soldier firebat = myBarrack.ProduceFirebat();
marine.attack();
firebat.attack();
}
}
抽象工厂SolderFactory接口声明了两种方法,生产机枪兵和生产火焰兵。每个兵种都能够攻击,因此它们均继承于Soldier接口。我们定义了Marine和Firebat类,将这两种兵种的行为实现了。最后,为了实现生产兵种,我们定义了一个兵营类Barracks,并实现了SolderFactory中的方法,分别在ProduceMarine和ProduceFirebat中实现了生产机枪兵和火焰兵的方法,并作为方法的返回值返回。
在main方法中,我们看到了,我们先实例化了一个兵营myBarracks,然后用ProduceMarine和ProduceFirebat实现了兵种的生产,最后我们可以调用兵种的attack方法来让他们用自己的方式攻击。
这里需要注意的是,我们在声明marine和firebat对象时,我们始终用的是Soldier这个接口来定义的,而不是用它们具体的类(Marine、Firebat)来进行定义。为什么要这么做?主要的原因还是为了实现分离,降低代码的耦合度;另外Marine和Firebat类,可能会存在别的方法,用Soldier来进行声明的话,就只会把attack方法暴露给我们。
抽象工厂模式的缺点也是显而易见的。假设我们要为工厂增加幽灵特工(Ghost,也就是我们俗称的原子弹兵)和医疗兵,我们不得不修改SoldierFactory,为它增加ProduceGhost和ProduceMedic方法声明,这是不利于我们进行扩展的。也就是说,它难以支持新种类的产品。