工厂方法模式

模式意图

Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

定义一个创建对象的接口,但是让子类决定怎么进行实例化。工厂方法让一个类的实例化进程延迟到子类。

It provides a way to delegate the instantiation logic to child classes.

它提供了一种将实例化逻辑委托给子类的方式。
维基百科队对于工厂方法模式的解释:

In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

工厂方法模式的使用场景

工厂方法模式适用于以下场景:

  • 一个类想要它的子类来指定具体创建的对象。
  • classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate(啥意思?)

具体实例

兽人(Orc)和精灵(Elf)两个部落都有铁匠(BlackSmith)。每个铁匠就相当于是一个工厂,BlackSmith有两个具体的实现,兽人有兽人的铁匠(OrcBlackSmith)、精灵有精灵的铁匠(ElfBlackSmith)。这样铁匠作为一个工厂就将具体的创造任务委托给了子类。
他们之间的类图关系如图所示:
工厂方法模式类图

代码如下,BlackSmith是一个工厂的接口,有一个manufactureWeapon()的方法。

1
2
3
4
5
6
7
8
/**
*
* The interface containing method for producing objects.
*
*/
public interface Blacksmith {
Weapon manufactureWeapon(WeaponType weaponType);
}

它有两个实现类,这两个类是工厂的具体实现,负责制造武器(manufactureWeapon):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
*
* Concrete subclass for creating new objects.
*
*/
public class OrcBlacksmith implements Blacksmith {

public Weapon manufactureWeapon(WeaponType weaponType) {
return new OrcWeapon(weaponType);
}
}
/**
*
* Concrete subclass for creating new objects.
*
*/
public class ElfBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return new ElfWeapon(weaponType);
}
}

客户端的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
// Lets go to war with Orc weapons
App app = new App(new OrcBlacksmith());
app.manufactureWeapons();

// Lets go to war with Elf weapons
app = new App(new ElfBlacksmith());
app.manufactureWeapons();
}

private void manufactureWeapons() {
Weapon weapon;
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
LOGGER.info(weapon.toString());
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
LOGGER.info(weapon.toString());
}

输出结果:

1
2
3
4
19:21:09.545 [main] INFO com.iluwatar.factory.method.App - Orcish spear
19:21:09.548 [main] INFO com.iluwatar.factory.method.App - Orcish axe
19:21:09.548 [main] INFO com.iluwatar.factory.method.App - Elven spear
19:21:09.548 [main] INFO com.iluwatar.factory.method.App - Elven axe