工厂模式的目的是将一些代码与其使用的对象的运行时类型分离:
// This code doesn't need to know that the factory is returning
// an object of type `com.example.parties.SurpriseParty`
AbstractParty myParty = new PartyFactory().create(...);
使用这样的代码,PartyFactory
专门负责确定或确切知道应该使用什么运行时类型。
通过传入所需类的完全限定名称,您将放弃该好处。这怎么样...
// This code obviously DOES know that the factory is returning
// an object of type `com.example.parties.SurpriseParty`.
// Now only the compiler doesn't know or enforce that relationship.
AbstractParty myParty = new PartyFactory().create("com.example.parties.SurpriseParty");
...与简单地声明myParty
为 type有什么不同com.example.parties.SurpriseParty
?最后你的代码是耦合的,但是你放弃了静态类型验证。这意味着您在放弃 Java 强类型化的一些好处的同时获得的好处也不少。如果你删除com.example.parties.SurpriseParty
你的代码仍然可以编译,你的 IDE 不会给你任何错误信息,而且你不会意识到这段代码和com.example.parties.SurpriseParty
运行时之间存在关系——这很糟糕。
至少,我建议您至少更改此代码,以便方法的参数是一个简单的类名,而不是完全限定名:
// I took the liberty of renaming this class and it's only method
public class MyPartyFactory{
public Party create(String name)
{
//TODO: sanitize `name` - check it contains no `.` characters
Class c = Class.forName("com.example.parties."+name);
// I'm going to take for granted that I don't have to explain how or why `party` shouldn't be an instance variable.
Party party = (PersonalParty)c.newInstance();
return party;
}
}
下一个:使用是不好的做法Class.forName(...)
吗?这取决于替代方案是什么,以及这些String
参数 ( name
) 与该工厂将提供的类之间的关系。如果替代方案是一个很大的条件:
if("SurpriseParty".equals(name) {
return new com.example.parties.SurpriseParty();
}
else if("GoodbyeParty".equals(name)) {
return new com.example.parties.GoodbyeParty();
}
else if("PartyOfFive".equals(name)) {
return new com.example.parties.PartyOfFive();
}
else if(/* ... */) {
// ...
}
// etc, etc etc
...这不是可扩展的。由于该工厂创建的运行时类型的名称与参数的值之间存在明显的可观察关系,因此name
您应该考虑Class.forName
改用。这样Factory
,每次Party
向系统添加新类型时,您的对象就无需更改代码。
您可以考虑的其他事情是使用该AbstractFactory
模式。如果您的消费代码如下所示:
AbstractParty sParty = new PartyFactory().create("SurpriseParty");
AbstractParty gbParty = new PartyFactory().create("GoodByeParty");
...如果请求的经常发生的聚会类型数量有限,您应该考虑为这些不同类型的聚会采用不同的方法:
public class PartyFactory {
public Party getSurpriseParty() { ... }
public Party getGoodByeParty() { ... }
}
... 这将允许您利用 Java 的静态类型。
但是,此解决方案确实意味着每次添加新类型时Party
都必须更改工厂对象 - 因此反射解决方案还是AbstractFactory
更好的解决方案实际上取决于您添加Party
类型的频率和速度。每天一个新类型?使用反射。每十年一种新的派对类型?使用AbstractFactory
.