关于工厂方法模式的GoF章节:
定义用于创建对象的接口,但是让子类决定实例化的类。工厂方法允许类将实例化推迟到子类。
其思想是让子类决定要实例化哪个类,而GoF对该思想的实现是在超类中提供一个抽象方法,子类需要重写,从而提供自己的实例化逻辑。
我不明白的是,为什么要使用抽象方法来实现它,而不使用类成员(即工厂)。我来解释。
这是GoF的方式:
public abstract class Creator {
public void doStuff() {
Product product = createProduct();
/* etc. */
}
public abstract Product createProduct();
}用法:
MyCreator myCreator = new Creator() {
@Override
public Product createProduct() {
return new MyProduct();
}
}
myCreator.doStuff();但是为什么要费心子类等等呢?我建议这样做:
public class Creator {
private Factory factory;
/* constructor */
public Creator(Factory factory) {
this.factory = factory;
}
public void doStuff() {
Product product = factory.createProduct();
/* etc. */
}
}你就是这样用的:
MyFactory myFactory = new MyFactory();
Creator creator = new Creator(myFactory);
creator.doStuff();那么,GoF的方法有什么好处呢?为什么不将工厂组合到Creator类中,而不是使用抽象方法来表示它呢?
发布于 2015-02-27 15:01:05
为什么不将工厂组合到Creator类中,而不是使用抽象方法来表示它呢?
因为在这种情况下,客户端“知道”要实例化哪个Factory类,这违背了整个模式的目的。整个想法是,客户端不知道构建了什么工厂,它只调用一个抽象类。假设您将插件插入到您的框架中,一些第三方工厂提供程序,并且您不知道它们实例化了什么(也不关心),只要服务于这个目的。
发布于 2015-02-27 15:07:24
Factory方法模式用于赋予子类对它们生成的对象类型的控制权。在您的示例中,控制对象类型的不是子类,而是类的用户。
下面的示例是来自工厂方法模式上的Wikipedia条目的副本。我们有一个迷宫游戏,它存在两个变体:正常迷宫游戏和魔术迷宫游戏与适应规则。通常的迷宫游戏由正常的房间和魔术的迷宫游戏组成。
public class MazeGame {
public MazeGame() {
Room room1 = makeRoom();
Room room2 = makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}
protected Room makeRoom() {
return new OrdinaryRoom();
}
}
public class MagicMazeGame extends MazeGame {
@Override
protected Room makeRoom() {
return new MagicRoom();
}
}通过使用工厂方法模式,我们可以确保MagicMazeGame由MagicRooms组成,但我们仍然可以重用超类的部分。
在您的建议中,MazeGame类将更改为:
public class MazeGame {
public MazeGame(RoomFactory factory) {
Room room1 = factory.makeRoom();
Room room2 = factory.makeRoom();
room1.connect(room2);
this.addRoom(room1);
this.addRoom(room2);
}
}现在可以这样做:
MazeGame game1 = new MazeGame(new MagicRoomFactory());
MazeGame game2 = new MagicMazeGame(new OrdinaryRoomFactory());这是您想要防止的事情,因为这样就可以创建带有错误房间的MazeGames。
发布于 2015-02-27 15:06:51
在这些类型的情况下,使用实际的英语类型作为插图而不是像“产品”这样更抽象的术语是非常有用的。
所以,让我们以宠物为例,说每一种宠物都有一个家。狗有一只犬类)。
以你为例,我们应该:
Public void doStuff() {
Home home = factory.createHome();
}但在这种情况下,说狗养狗,鸟养笼子的逻辑又在哪里呢?它必须进入工厂对象-这反过来意味着在工厂逻辑中必须显式地重复宠物的继承层次结构。这反过来意味着,每次添加新类型的宠物时,都必须记住将该类型添加到Factory中。
工厂方法模式意味着您将拥有如下内容:
public class Pet {
private String name;
private Home home;
public Pet(String name) {
this.name = name;
this.home = this.createHome();
}
public abstract Home createHome();这允许您每次创建新类型的宠物时,都可以指定宠物类型的主页,而不必更改任何其他类,并且在此过程中还知道每个宠物类型都有一个Home。
例如:你可能会:
public class Dog extends Pet {
public Home createHome() {
return new Kennel();
}
}编辑以添加Dog示例
https://stackoverflow.com/questions/28767667
复制相似问题