工厂模式的目的是将一些代码与其所使用的对象的运行时类型解耦:
// 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
作为类型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 http://en.wikipedia.org/wiki/Abstract_factory_pattern图案代替。如果您的消费代码如下所示:
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
.