工廠模式
工廠模式也被稱(chēng)之為虛擬構(gòu)造函數(shù)(Virtual Constructor)状蜗,是Java中最常用的設(shè)計(jì)模式之一雹姊。這種類(lèi)型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對(duì)象的最佳方式。
在工廠模式中手销,我們?cè)趧?chuàng)建對(duì)象時(shí)不會(huì)對(duì)客戶端暴露創(chuàng)建邏輯,并且是通過(guò)使用一個(gè)共同的接口來(lái)指向新創(chuàng)建的對(duì)象
意圖
定義用于創(chuàng)建對(duì)象的接口图张,但是讓子類(lèi)決定實(shí)例化哪個(gè)類(lèi)锋拖。factory方法允許類(lèi)將實(shí)例化推遲到子類(lèi)
主要解決:接口選擇的問(wèn)題。
何時(shí)使用:我們明確地計(jì)劃不同條件下創(chuàng)建不同實(shí)例時(shí)埂淮。
如何解決:讓其子類(lèi)實(shí)現(xiàn)工廠接口姑隅,返回的也是一個(gè)抽象的產(chǎn)品。
關(guān)鍵代碼:創(chuàng)建過(guò)程在其子類(lèi)執(zhí)行倔撞。
解釋
現(xiàn)實(shí)世界的例子
鐵匠制造武器讲仰。精靈需要精靈武器,獸人需要獸人武器痪蝇。根據(jù)手頭的顧客鄙陡,召集合適類(lèi)型的鐵匠
簡(jiǎn)而言之
它提供了一種將實(shí)例化邏輯委托給子類(lèi)的方法
維基百科說(shuō)
In class-based programming, the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.
(在基于類(lèi)的編程中,factory方法模式是一種創(chuàng)建模式躏啰,它使用factory方法來(lái)處理創(chuàng)建對(duì)象的問(wèn)題趁矾,而不必指定將要?jiǎng)?chuàng)建的對(duì)象的確切類(lèi)。這是通過(guò)調(diào)用factory方法(在接口中指定并由子類(lèi)實(shí)現(xiàn)给僵,或者在基類(lèi)中實(shí)現(xiàn)并可選地由派生類(lèi)重寫(xiě))來(lái)實(shí)現(xiàn)的毫捣,而不是通過(guò)調(diào)用構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)的。)
程序代碼示例
以現(xiàn)實(shí)世界的例子鐵匠制造武器為例子帝际,需要什么樣的武器類(lèi)型我們就召喚對(duì)應(yīng)類(lèi)型的鐵匠蔓同。程序類(lèi)圖如下:
首先我們有一個(gè)鐵匠接口(定義了一個(gè)制造武器的方法)和一些精靈鐵匠、獸人鐵匠實(shí)現(xiàn)類(lèi):
public interface Blacksmith {
Weapon manufactureWeapon(WeaponType weaponType);
}
public class ElfBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return new ElfWeapon(weaponType);
}
}
public class OrcBlacksmith implements Blacksmith {
public Weapon manufactureWeapon(WeaponType weaponType) {
return new OrcWeapon(weaponType);
}
}
其次我們有一個(gè)武器接口(定義了一個(gè)獲取武器類(lèi)型的方法)和一些精靈武器蹲诀、獸人武器實(shí)現(xiàn)類(lèi):
/**
* Weapon interface.
*/
public interface Weapon {
WeaponType getWeaponType();
}
/**
* ElfWeapon.
*/
public class ElfWeapon implements Weapon {
private WeaponType weaponType;
public ElfWeapon(WeaponType weaponType) {
this.weaponType = weaponType;
}
@Override
public String toString() {
return "Elven " + weaponType;
}
@Override
public WeaponType getWeaponType() {
return weaponType;
}
}
/**
* OrcWeapon.
*/
public class OrcWeapon implements Weapon {
private WeaponType weaponType;
public OrcWeapon(WeaponType weaponType) {
this.weaponType = weaponType;
}
@Override
public String toString() {
return "Orcish " + weaponType;
}
@Override
public WeaponType getWeaponType() {
return weaponType;
}
}
最后斑粱,隨著顧客的到來(lái),正確類(lèi)型的鐵匠被召喚出來(lái)脯爪,要求制造武器
public class App {
private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
private final Blacksmith blacksmith;
/**
* Creates an instance of <code>App</code> which will use <code>blacksmith</code> to manufacture
* the weapons for war.
* <code>App</code> is unaware which concrete implementation of {@link Blacksmith} it is using.
* The decision of which blacksmith implementation to use may depend on configuration, or
* the type of rival in war.
* @param blacksmith a non-null implementation of blacksmith
*/
public App(Blacksmith blacksmith) {
this.blacksmith = blacksmith;
}
/**
* Program entry point
*
* @param args command line args
*/
public static void main(String[] args) {
// Lets go to war with Orc weapons
App app = new App(new OrcBlacksmith());
app.manufactureWeapons();
// Lets go to war with Elf weapons
app = new App(new ElfBlacksmith());
app.manufactureWeapons();
}
private void manufactureWeapons() {
Weapon weapon;
weapon = blacksmith.manufactureWeapon(WeaponType.SPEAR);
LOGGER.info(weapon.toString());
weapon = blacksmith.manufactureWeapon(WeaponType.AXE);
LOGGER.info(weapon.toString());
}
}
運(yùn)行App程序結(jié)果:
適用場(chǎng)景
當(dāng)遇到如下三種情況時(shí)则北,應(yīng)使用工廠模式:
- 一個(gè)類(lèi)不能預(yù)測(cè)它必須創(chuàng)建的對(duì)象的類(lèi)
- 一個(gè)類(lèi)希望它的子類(lèi)指定它創(chuàng)建的對(duì)象
- 類(lèi)將責(zé)任委托給幾個(gè)助手子類(lèi)中的一個(gè),并且你希望本地化哪個(gè)助手子類(lèi)是委托的責(zé)任
Java中的現(xiàn)實(shí)例子
- java.util.Calendar
- java.util.ResourceBundle
- java.text.NumberFormat
- java.nio.charset.Charset
- java.net.URLStreamHandlerFactory
- java.util.EnumSet
- javax.xml.bind.JAXBContext
優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1痕慢、一個(gè)調(diào)用者想創(chuàng)建一個(gè)對(duì)象尚揣,只要知道其名稱(chēng)就可以了。
2守屉、擴(kuò)展性高惑艇,如果想增加一個(gè)產(chǎn)品,只要擴(kuò)展一個(gè)工廠類(lèi)就可以。
3滨巴、屏蔽產(chǎn)品的具體實(shí)現(xiàn)思灌,調(diào)用者只關(guān)心產(chǎn)品的接口
缺點(diǎn):
每次增加一個(gè)產(chǎn)品時(shí),都需要增加一個(gè)具體實(shí)現(xiàn)類(lèi)和修改對(duì)象實(shí)現(xiàn)工廠恭取,使得系統(tǒng)中類(lèi)的個(gè)數(shù)成倍增加泰偿,在一定程度上增加了系統(tǒng)的復(fù)雜度,同時(shí)也增加了系統(tǒng)具體類(lèi)的依賴蜈垮。這并不是什么好事
寫(xiě)在最后
工廠模式作為一種創(chuàng)建類(lèi)模式耗跛,在任何需要生成復(fù)雜對(duì)象的地方,都可以使用工廠模式攒发,比如設(shè)計(jì)一個(gè)連接服務(wù)器的框架调塌,需要三個(gè)協(xié)議,"POP3"惠猿、"IMAP"羔砾、"HTTP",可以把這三個(gè)作為產(chǎn)品類(lèi)偶妖,共同實(shí)現(xiàn)一個(gè)通訊接口姜凄。
對(duì)于簡(jiǎn)單對(duì)象,特別是只需要通過(guò)new就可以完成創(chuàng)建的對(duì)象趾访,無(wú)需使用工廠模式态秧,因?yàn)槭褂霉S模式必然要引入一個(gè)工廠類(lèi),這會(huì)增加系統(tǒng)的復(fù)雜度扼鞋,切不可為了設(shè)計(jì)模式而模式申鱼。
下一篇文章我們將在工廠模式的基礎(chǔ)上繼續(xù)延伸介紹抽象工廠模式,難度系統(tǒng)為中級(jí)
碼字不易云头,各位看官喜歡的話润讥,請(qǐng)給點(diǎn)個(gè)贊??,如果你對(duì)接下來(lái)的文章有什么建議或者要求可在評(píng)論中積極留言盘寡,謝謝大家!