我是设计模式的新手。在浏览GOF时,实现工厂模式的一种方法是创建与每个产品相对应的创建者(工厂)的并行层次结构。为什么我们需要这种层次结构?它不会创建不必要的子类吗? 有人可以给我一个我们需要这种实现的例子。
答案 0 :(得分:1)
如果您不希望在使用它们的上下文中决定要创建哪个对象,但想要推迟它,则需要此模式。您可以使用工厂模式将决策推迟到运行时。
这是一个例子(有点过于简单,但我希望你明白这一点):
您想要编写一个创建NumberObject
的程序,并且您希望拥有一个简单的类型或复杂的类型。但是你不想硬编码决定在你的程序中使用哪种数字对象,但是想根据你编程的命令行参数来制作它。
首先,您创建了2个类SimpleNumberObject
和ComplexNumberObject
,它们都实现了具有抽象方法NumberObject
的类print()
,并强制子类实现它。类似的东西:
public class NumberObject {
protected int number;
public NumberObject(int number) {
this.number = number;
}
abstract void print();
}
public class SimpleNumberObject extends NumberObject {
public SimpleNumberObject(int number) {
super(number);
}
public void print() {
System.out.println("My number is " + number);
}
}
public class ComplexNumberObject() extends NumberObject {
public SimpleNumberObject(int number) {
super(number);
}
public void print() {
System.out.println("My number is " + number
+ " and I can do a lot more complex stuff");
}
}
然后使用方法NumberFactory
和子类createNumber()
和SimpleNumberFactory
创建抽象类ComplexNumberFactory
,它们必须实现此方法,然后返回相应的NumberObject:SimpleNumberFactory
一个SimpleNumberObject
和ComplexNumberFactory
一个ComplexNumberObject
(我将跳过这里的实现,如果你需要它来理解让我知道,那么我也可以把它。)
然后,您设计主类,如果要使用SimpleNumberObject
或ComplexNumberObject
,您可以在构造函数中进行设计。
public class MainClass {
private NumberFactory numberFactory;
public MainClass(String arg) {
if (arg != null && arg.equals("complex") {
numberFactory = new ComplexNumberFactory();
} else {
numberFactory = new SimpleNumberFactory();
}
}
public void printSomeNumber() {
NumberObject number = numberFactory.createNumber();
number.print();
}
public static void main(String[] args) {
MainClass mainClass = new MainClass(args[0]);
mainClass.printSomeNumber();
}
}
所以这里发生的是根据命令行参数,它将创建SimpleNumberObjects或ComplexNumberObjects。您没有在代码中指定它,因此编译器无法确定将使用哪个对象,只是它实现了NumberObject
。
使用工厂,您将从MainClass
如何创建一个数字开始承担责任。他们可以使用随机生成器来生成NumberObject构造函数所需的整数,或者一些迭代数。事实上,主要课程不需要关心,而且你将它解耦了一点。
关于推迟决定创建什么对象:它不一定必须是命令行参数,而是可以是不同的类,某些上下文信息或其他内容。基本上,如果你想在其他地方做出决定,你可以使用这个模式,当然如果你想将对象的创建委托给工厂。
你是对的,有很多子类正在进行,这使得这个模式类很重。在实践中,你必须决定使用它是否有回报。如果您打算使用工厂进行对象创建,那么无论如何您都有不同的对象子类,并且您不必决定在程序中的某个点创建哪个子类,那么您可能会考虑使用它。