为什么要把工厂方法和抽象工厂放在一起呢?因为这两个名字里面都有工厂,容易弄混。
工厂方法
工厂方法,就是定义一个实例化函数的接口,然后让子类决定实例化哪一个。和之前说的策略模式颇有相似之处,只不过工厂方法是针对创建,而策略模式是针对行为。具体可以参考这里。
代码
来看看具体的代码例子。
首先有一个铁匠接口,功能是制造武器,也就是**工厂方法:
/**
*
* The interface containing method for producing objects.
*
*/
public interface Blacksmith {
Weapon manufactureWeapon(WeaponType weaponType);
}
那么还需要武器的接口和武器类型:
/**
* Weapon interface.
*/
public interface Weapon {
WeaponType getWeaponType();
}
/**
*
* WeaponType enumeration
*
*/
public enum WeaponType {
SHORT_SWORD("short sword"), SPEAR("spear"), AXE("axe"), UNDEFINED("");
private String title;
WeaponType(String title) {
this.title = title;
}
@Override
public String toString() {
return title;
}
}
现在我们想要制造精灵族的武器,那么首先定义:
/**
* ElfWeapon.
*/
public class ElfWeapon implements Weapon {
private WeaponType weaponType;
public ElfWeapon(WeaponType weaponType) {
this.weaponType = weaponType;
}
@Override
public String toString() {
return "Elven " + weaponType;
}
@Override
public WeaponType getWeaponType() {
return weaponType;
}
}
然后定义精灵铁匠。
/**
*
* Concrete subclass for creating new objects.
*
*/
public class ElfBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return new ElfWeapon(weaponType);
}
}
实际使用起来和策略模式很像,我们只需要定义一个Blacksmith接口类,在要创建实例的时候new一个新的精灵铁匠给Blacksmith,然后再制造武器即可。假如有兽人铁匠,亦可切换。
一个很重要的问题:工厂在哪里?或者说谁是工厂?
答案就是,生产武器的那个方法是工厂。这就是所谓的工厂方法。
抽象工厂
所谓抽象工厂,就是给出一个创造一系列相关对象的接口但是不指明具体的类。
例如,一个王国类(Kingdom)需要构造三个类:国王(King),军队(Army)和城堡(Castle):
/**
*
* King interface
*
*/
public interface King {
String getDescription();
}
/**
*
* Army interface
*
*/
public interface Army {
String getDescription();
}
/**
*
* Castle interface
*
*/
public interface Castle {
String getDescription();
}
王国的抽象工厂,这个工厂里面有三个工厂方法:
/**
*
* KingdomFactory factory interface.
*
*/
public interface KingdomFactory {
Castle createCastle();
King createKing();
Army createArmy();
}
精灵王国的工厂:
/**
*
* ElfKingdomFactory concrete factory.
*
*/
public class ElfKingdomFactory implements KingdomFactory {
public Castle createCastle() {
return new ElfCastle();
}
public King createKing() {
return new ElfKing();
}
public Army createArmy() {
return new ElfArmy();
}
}
这里的Elf前缀的类当然也是前面那些接口的实现类,很简单,这里就不贴出来了。
等到要构造王国实例的时候,可以传入一个具体工厂,用工厂来制造对应的军队类等等。
区别
具体参考这里。
简单来说,工厂方法是一个方法,而抽象工厂是一个类。两者不是一个层面上的东西。你也可以说Blacksmith是一个抽象工厂,不过一般都认为抽象工厂是包含多个工厂方法的。