我正在阅读以下链接:
我注意到在使用工厂模式时,我见过的所有示例都在工厂中使用了无参数构造函数。在最后一个链接中,它建议如果参数增长,则考虑使用构建器模式。我知道何时以及如何使用构建器模式,但工厂模式让我感到困惑。如果您有包含参数的子类会发生什么,其中一些参数对于子类是唯一的?在这种情况下你做什么?
举个例子:
让我们说你有以下抽象类:
public abstract class Client {
private String clientID;
private String clientFirstName;
private String clientLastName;
public Client(String ID, String firstname, String lastname)
{
this.clientID = ID;
this.clientFirstName = firstname;
this.clientLastName = lastname;
}
}
以及以下子类:
public class Domestic extends Client {
public Domestic(String ID, String firstname, String lastname) {
super(ID, firstname, lastname);
}
}
public class International extends Client {
private List<String> documents;
public International(String ID, String firstname, String lastname, List<String> documents) {
super(ID, firstname, lastname);
this.documents = documents;
}
现在,这些论点还不足以使用构建器模式吗?简单地这样做有什么不妥之处:
Client international = new International(id, firstname, lastname, documents);
或
International internationalObj = new International(id, firstname, lastname, documents);
答案 0 :(得分:2)
当您确定实际需要一棵树时会发生什么:
Client
|
-- Domestic Client
|
-- International_client
|
|_ APAC Client
|
|_ EMEA client
|
|_ South America Client
|
|_ I'm not very creative, but imagine there are a bunch more.
突然间,当你需要实例化对象时,你的代码会像:
if (domestic) {
client = new DomesticClient(...);
} else if (international) {
if (apac) {
client = new APACClient();
} else if (emea) {
client = new EMEAClient();
} else if (sa) {
client = new SouthAmericaClient();
}
...
}
随着可能性数量的增加,您希望在代码库周围出现这种问题的可能性会下降。也许你甚至不希望呼叫者需要知道他们拥有什么样的客户端。抽象应该隐藏不同的实现,对吧?作为客户,我为什么需要知道John Smith客户ID 1234是国际的。也许我希望能够打电话:
Client c = Client.ForCustomerId(id);
或者
Client c = Client.Build(id, firstname, lastname, documents);
神奇地获得适当的客户类型,而不知道他们真正的客户类型。
当您查看一个小问题时,许多设计模式在效用方面没有多大意义。当问题变得相当复杂时,它们就会闪耀。例如。 IMO构建器模式在这里不会太有用 - 如果A)具有TON选项,或者B)根据不同的用例具有变化/可选选项,则更有用。你所描述的有一组固定的小参数。
现在,如果您开始添加一堆参数 - 也许您需要为美国客户提供SSN或为欧盟客户提供增值税信息等等 - 也许有必要转移到生成器,当您拥有它们时,并最终生成对象。