在最初的學(xué)習(xí)過程中對把簡單的東西搞得復(fù)雜的現(xiàn)象很不理解像鸡,隨著經(jīng)驗的增長逆皮,慢慢發(fā)現(xiàn)我所理解的“簡單”其實是針對設(shè)計的簡單由蘑,這種代碼缺少靈活性,目的僅僅是為了解決現(xiàn)有問題帮碰。而“復(fù)雜”恰恰是針對一類問題的萬能方案相味,他可以讓代碼變得優(yōu)雅,靈活不再是一個臃腫的胖子殉挽。
在對模式的學(xué)習(xí)過程中很容易誤入歧途丰涉,陷入形式主義,對模式細(xì)節(jié)的過多關(guān)注恰恰使我們越陷越深斯碌,子曾經(jīng)曰過:“學(xué)而不思則罔”一死,文檔中的類圖和實現(xiàn)代碼往往并不能代表模式的全部,我們學(xué)習(xí)模式的重點要放在模式的意圖上傻唾。
設(shè)計模式代表了最佳的實踐投慈,是開發(fā)人員在開發(fā)過程中面臨一般問題的解決方案,是眾多前輩們在經(jīng)過相當(dāng)長一段時間的試驗和錯誤中總結(jié)出來的冠骄。
什么是設(shè)計模式
設(shè)計模式:是一套被反復(fù)使用逛裤、多數(shù)人知曉、經(jīng)過分類編目的代碼設(shè)計經(jīng)驗的總結(jié)猴抹。
使用設(shè)計模式的目的
使用設(shè)計模式是為了重用代碼带族、讓代碼更容易被他人理解、保證代碼的可靠性蟀给。
設(shè)計模式的分類
- 創(chuàng)建型模式:創(chuàng)建型模式涉及對象的實例化蝙砌,用于解耦對象的實例化過程,不讓用戶代碼依賴于對象的創(chuàng)建或排列方式跋理,避免用戶直接使用new創(chuàng)建對象择克。。
- 結(jié)構(gòu)型模式:把類或?qū)ο蠼Y(jié)合在一起形成一個更大的結(jié)構(gòu)前普,和類有關(guān)的結(jié)構(gòu)型模式涉及如何合理使用繼承機制肚邢;和對象有關(guān)的結(jié)構(gòu)型模式涉及如何合理的使用對象組合機制。。
- 行為型模式: 行為型模式涉及怎樣合理的設(shè)計對象之間的交互通信骡湖,以及怎樣合理為對象分配職責(zé)贱纠,讓設(shè)計富有彈性,易維護(hù)响蕴,易復(fù)用谆焊。
工廠模式
意圖:定義一個創(chuàng)建對象的接口。讓其子類決定實例化哪一個類浦夷。使其實例化過程延遲到子類進(jìn)行辖试。
工廠模式中,我們在創(chuàng)建對象時不會對客戶端暴露創(chuàng)建邏輯劈狐,并且是通過使用一個共同的接口來指向新創(chuàng)建的對象罐孝。
三個工廠
-
簡單工廠模式
簡單工廠模式又叫靜態(tài)工廠方法模式,實際不能算作一種設(shè)計模式肥缔。
GOF在《設(shè)計模式》一書中將工廠模式分為兩類:工廠方法模式與抽象工廠模式莲兢。將簡單工廠模式看為工廠方法模式的一種特例,兩者歸為一類辫继。
意圖:定義一個用于創(chuàng)建對象的接口
具體實現(xiàn):
抽象一個產(chǎn)品基類怒见,(接口也可以)
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:產(chǎn)品的抽象類
*/
public abstract class Coffee {
/**
* 展示產(chǎn)品詳情
*/
public abstract void details();
}
產(chǎn)品的具體實現(xiàn)
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description: 美式咖啡
*/
public class Americano extends Coffee {
@Override
public void details() {
System.out.print("美式咖啡,不便宜");
}
}
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:拿鐵咖啡
*/
public class Latte extends Coffee {
@Override
public void details() {
System.out.print("拿鐵咖啡,不便宜");
}
}
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:雀巢咖啡
*/
public class Nescafe extends Coffee {
@Override
public void details() {
System.out.print("雀巢咖啡,喝得起");
}
}
簡單工廠來創(chuàng)建不同類型的咖啡實例
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description: 簡單工廠
*/
public class SimpleFactory {
/**
* 通過傳遞過來的類型創(chuàng)建不同實例
* @param type
* @return
*/
public static Coffee createInstance(String type) {
if (type.equals("Americano")) {
return new Americano();
} else if (type.equals("Latte")) {
return new Latte();
} else if (type.equals("Nescafe")) {
return new Nescafe();
} else {
throw new RuntimeException("沒有匹配到可實例化[" + type + "]對象");
}
}
}
使用
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:
*/
public class Test {
public static void main(String[] args) {
Coffee latte = SimpleFactory.createInstance("Latte");
latte.details();
Coffee americano = SimpleFactory.createInstance("Americano");
americano.details();
Coffee nescafe = SimpleFactory.createInstance("Nescafe");
nescafe.details();
}
}
簡單工廠模式在實際使用過程中,對產(chǎn)品部分來說是符合開閉原則的姑宽,但是對于工廠部分遣耍,每增加一個新產(chǎn)品,都要在工廠類中增加相應(yīng)的創(chuàng)建邏輯炮车,這顯然違背了開閉原則舵变。
不知道設(shè)計模式六大原則的同學(xué)請自行補課
http://www.runoob.com/design-pattern/design-pattern-intro.html
-
工廠方法模式
意圖:提供一個用于創(chuàng)建對象的接口(工廠接口),讓其實現(xiàn)類(工廠實現(xiàn)類)決定實例化哪一個類(產(chǎn)品類)瘦穆,并且由該實現(xiàn)類創(chuàng)建對應(yīng)類的實例纪隙。
可以理解為不同地區(qū)只生產(chǎn)自己類型的咖啡,美國America只生產(chǎn)Americano扛或,德國Germany只生產(chǎn)Latte和Nescafe绵咱。
具體實現(xiàn):
產(chǎn)品基類及實現(xiàn)同上
定義一個工廠基類,(使用接口的方式會更好)
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:定義一個抽象咖啡工廠
*/
public abstract class CoffeeFactory {
/**
* 用于生產(chǎn)咖啡
* @return
*/
public abstract Coffee createCoffee(String type);
}
咖啡工廠的具體實現(xiàn)
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:美國咖啡工廠
*/
public class AmericaCoffeeFactory extends CoffeeFactory{
@Override
public Coffee createCoffee(String type) {
return new Americano();
}
}
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:德國咖啡工廠
*/
public class GermanyCoffeeFactory extends CoffeeFactory {
@Override
public Coffee createCoffee(String type) {
if (type.equals("Latte")) {
return new Latte();
} else if (type.equals("Nescafe")) {
return new Nescafe();
} else {
throw new RuntimeException("沒有匹配到可實例化[" + type + "]對象");
}
}
}
使用
public class Test {
public static void main(String[] args) {
/**
* 工廠方法模式的使用方法
*/
CoffeeFactory americaCoffeeFactory = new AmericaCoffeeFactory();
Coffee americaCoffees = americaCoffeeFactory.createCoffee("");
americaCoffees.details();
CoffeeFactory germanyCoffeeFactory = new GermanyCoffeeFactory();
Coffee latteCoffees = germanyCoffeeFactory.createCoffee("Latte");
latteCoffees.details();
Coffee nescafeCoffees = germanyCoffeeFactory.createCoffee("Nescafe");
nescafeCoffees.details();
}
}
工廠方法模式非常符合“開閉原則”熙兔,當(dāng)需要增加一個新的產(chǎn)品時悲伶,我們只需要增加一個具體的產(chǎn)品類和與之對應(yīng)的具體工廠即可,無須修改原有系統(tǒng)住涉。但是由于每新增一個新產(chǎn)品時就需要增加兩個類麸锉,這樣勢必會導(dǎo)致系統(tǒng)的復(fù)雜度增加。
-
抽象工廠模式
場景:當(dāng)需要創(chuàng)建的對象是一系列相互關(guān)聯(lián)或相互依賴的產(chǎn)品族時舆声,便可以使用抽象工廠模式花沉。
意圖:為創(chuàng)建一組相關(guān)或相互依賴的對象提供一個接口,而且無需指定他們的具體類。抽象工廠為不同產(chǎn)品族的對象創(chuàng)建提供接口碱屁。
關(guān)鍵點在于如何在一個工廠里聚合多個同類產(chǎn)品磷脯。
具體實現(xiàn):
抽象出飲料制造工廠
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:
*/
public interface AbstractDrinksFactory {
/**
* 制造咖啡
* @return
*/
Coffee createCoffee();
/**
* 制造碳酸飲料
* @return
*/
Sodas createSodas();
/**
* 制造茶
* @return
*/
Tea createTea();
}
飲料工廠的具體實現(xiàn)
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:美國飲料工廠
*/
public class AmericaDrinksFactory implements AbstractDrinksFactory{
@Override
public Coffee createCoffee() {
return new Latte();
}
@Override
public Sodas createSodas() {
return new CocaCola();
}
@Override
public Tea createTea() {
return null;
}
}
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:中國飲料工廠
*/
public class ChinaDrinksFactory implements AbstractDrinksFactory{
@Override
public Coffee createCoffee() {
return new Latte();
}
@Override
public Sodas createSodas() {
return new CocaCola();
}
@Override
public Tea createTea() {
return new Dragon_Well();
}
}
使用
/**
* @Author: chichapaofan
* @CreateDate: 2018/10/24
* @Description:
*/
public class Test {
public static void main(String[] args) {
/**
* 抽象工廠測試
*/
AbstractDrinksFactory chinaDrinksFactory = new ChinaDrinksFactory();
Coffee coffee = chinaDrinksFactory.createCoffee();
Sodas sodas = chinaDrinksFactory.createSodas();
Tea tea = chinaDrinksFactory.createTea();
if (coffee != null) {
coffee.details();
}
if (sodas != null) {
sodas.details();
}
if (tea != null) {
tea.details();
}
}
}
抽象工廠模式最主要的優(yōu)點就是可以在類的內(nèi)部對產(chǎn)品族進(jìn)行約束,而不必專門引入一個新的類來進(jìn)行管理忽媒。
當(dāng)然抽象工廠模式的缺點也非常明顯争拐,那就是產(chǎn)品族的不易擴展腋粥,使產(chǎn)品族中每需要增加一個新的產(chǎn)品晦雨,則幾乎所有的工廠類都需要進(jìn)行修改。所以使用抽象工廠模式時隘冲,對產(chǎn)品等級結(jié)構(gòu)的劃分是非常重要的闹瞧。
參考文章:
http://www.runoob.com/design-pattern/abstract-factory-pattern.html
https://www.cnblogs.com/zailushang1996/p/8601808.html
https://www.cnblogs.com/carryjack/p/7709861.html