工廠模式的目的是去耦合一些代碼從它消耗對象的運行時類型:
// 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
代替。這樣,每次向系統添加新的Party
類型時,您的Factory
對象都不需要更改代碼。
你可以考慮的其他東西是使用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
。
這是否有任何嚴重的用例。一般來說,我會考慮反思作爲我的最後手段。特別是爲了這個目的。 –
JSf2.0這樣的框架如何使用註釋?它們應該使用Reflection API在運行時實例化對象? – Ullas
如果是關於JSF,那麼請標籤是這樣的。 –