我是设计模式的新手。在通过 GOF 时,实现工厂模式的一种方法是创建与每个产品对应的创建者(工厂)的并行层次结构。为什么我们需要这种层次结构?它不会创建不必要的子类吗?有人可以给我一个我们需要这种实现的例子吗?
1 回答
如果您不想决定要在使用它们的上下文中创建什么对象,但想推迟它,则需要此模式。您可以使用工厂模式将决定推迟到运行时。
这是一个例子(有点过于简单了,但我希望你明白这一点):
您想编写一个创建NumberObject
s 的程序,并且您希望拥有一种简单的或复杂的。但是您不想硬编码决定在程序中使用哪种数字对象,而是希望根据程序的命令行参数来决定。
首先,您创建 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
and ComplexNumberFactory
,它们必须实现此方法,它们在其中返回各自的 NumberObject:SimpleNumberFactory
aSimpleNumberObject
和ComplexNumberFactory
a 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 构造函数需要的整数,或者一些迭代数字。事实上,主类不需要关心,你将它解耦了一点。
关于推迟决定创建什么对象:它不一定是命令行参数,但可以是不同的类、一些上下文信息或其他东西。基本上,如果您想在其他地方做出决定,当然如果您想将对象的创建委托给工厂,则可以使用此模式。
你是对的,有很多子类化正在进行,这使得这种模式有点重类。在实践中,您必须决定使用它是否值得。如果您无论如何都要使用工厂来创建对象,那么无论如何您都有不同的对象子类,并且对您来说重要的是您不要决定在程序中的某个点创建哪个子类,那么您可能会考虑使用它。