序言
做開(kāi)發(fā)久一點(diǎn)的都知道設(shè)計(jì)模式名眉,你很多人看了很多書(shū)籍和文章粟矿,但因用了設(shè)計(jì)模式而收益匪淺的人可能不是很多。這又是為什么呢损拢?
下面我們以工廠模式為切入點(diǎn)陌粹,循序漸進(jìn)的來(lái)理解設(shè)計(jì)模式
- what is it?福压?
- How do we use it掏秩?
- What does it can bring to us?
工廠模式
分三種:簡(jiǎn)單工廠模式荆姆、工廠方法模式蒙幻、抽象工廠模式
1、普通工廠模式
描述:如果你有一個(gè)接口胞枕,想new一個(gè)實(shí)現(xiàn)類(lèi)的對(duì)象,不要直接new魏宽,而是通過(guò)另外一個(gè)類(lèi)來(lái)獲得這個(gè)對(duì)象腐泻,另外的這個(gè)類(lèi)就叫工廠類(lèi)决乎。
代碼舉例(假設(shè)有A和B兩個(gè)同事合作完成這個(gè)工程):
// 同事A的代碼
/** 定義一個(gè)“移動(dòng)電話(huà)”接口 */
public interface MobilePhone {
public void call(String phoneNumber);
}
/** 主程序中調(diào)用 */
public class MyTest {
private MobilePhone androidPhone;
private MobilePhone iPhone;
private MobilePhone windowsPhone;
public static void main(String[] args) {
// 等同事B寫(xiě)完工廠類(lèi)再把下面三行創(chuàng)建對(duì)象的代碼加進(jìn)來(lái)
// 通過(guò)傳參來(lái)創(chuàng)建對(duì)象,參數(shù)一定不能寫(xiě)錯(cuò)
androidPhone = PhoneFactory.createMobilePhone("Android");
iPhone = PhoneFactory.createMobilePhone("iPhone");
windowsPhone = PhoneFactory.createMobilePhone("Windows");
if (androidPhone != null) androidPhone.call("13900000000");
if (iPhone != null) iPhone.call("13900000000");
if (windowsPhone != null) windowsPhone.call("13900000000");
}
}
// 同事B的代碼
/** 創(chuàng)建工廠類(lèi) */
public class PhoneFactory {
public static MobilePhone createMobilePhone(String phoneKind) {
if (phoneKind.equalsIgnoreCase("Android")) {
return new AndroidPhone();
} else if (phoneKind.equalsIgnoreCase("iPhone")) {
return new IPhone();
} else if (phoneKind.equalsIgnoreCase("Windows")) {
return new WindowsPhone();
}
return null;
}
}
/** 手機(jī)的實(shí)現(xiàn)類(lèi) */
public class AndroidPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use AndroidPhone");
}
}
public class IPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use iPhone");
}
}
public class WindowsPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use WindowsPhone");
}
}
作用:如果你跟另外一個(gè)同事合作寫(xiě)代碼派桩,你負(fù)責(zé)調(diào)用MobilePhone接口中的方法构诚,他負(fù)責(zé)寫(xiě)MobilePhone實(shí)現(xiàn)類(lèi),就可以考慮用工廠模式铆惑,當(dāng)有一天你的那個(gè)同事想改一成另外一個(gè)實(shí)現(xiàn)類(lèi)范嘱,他不用通知你,只需要新寫(xiě)一個(gè)實(shí)現(xiàn)類(lèi)再改一下工廠類(lèi)就可以了员魏。
缺點(diǎn):你要等你同事寫(xiě)好工廠類(lèi)之后再開(kāi)始開(kāi)發(fā)丑蛤,沒(méi)有做到解耦。
2撕阎、工廠方法模式
描述:前邊講的簡(jiǎn)單工廠模式是你通過(guò)傳參告訴工廠類(lèi)你想要什么產(chǎn)品受裹,工廠類(lèi)幫你生產(chǎn),因?yàn)檫@個(gè)工廠可以生產(chǎn)很多種產(chǎn)品虏束。
而工廠方法模式是:有很多工廠棉饶,每個(gè)工廠只能生產(chǎn)單一的一種產(chǎn)品,你想要哪種產(chǎn)品镇匀,就直接去找生產(chǎn)那種產(chǎn)品的工廠就好照藻,不用傳參了。
當(dāng)然這一大堆工廠有一個(gè)統(tǒng)一的工廠接口汗侵,這一大堆產(chǎn)品也有一個(gè)統(tǒng)一的產(chǎn)品接口幸缕。
代碼舉例:
// 同事A的代碼
/** 定義一個(gè)“移動(dòng)電話(huà)”接口 */
public interface MobilePhone {
public void call(String phoneNumber);
}
/** 創(chuàng)建工廠類(lèi)接口 */
public interface PhoneFactory {
public static MobilePhone createMobilePhone();
}
/** 主程序中調(diào)用 */
public class MyTest {
private MobilePhone androidPhone;
private MobilePhone iPhone;
private MobilePhone windowsPhone;
// 要?jiǎng)?chuàng)建多個(gè)工廠對(duì)象
private PhoneFactory androidPhoneFactory;
private PhoneFactory iPhoneFactory;
private PhoneFactory windowsPhoneFactory;
public static void main(String[] args) {
// 等同事B寫(xiě)完工廠類(lèi)再把下面幾行創(chuàng)建對(duì)象的代碼加進(jìn)來(lái)
androidPhoneFactory = new AndroidPhoneFactory();
iPhoneFactory = new IPhoneFactory();
windowsPhoneFactory = new WindowsPhoneFactory();
// 現(xiàn)在就不用傳參了
androidPhone = androidPhoneFactory.createMobilePhone();
iPhone = iPhoneFactory.createMobilePhone();
windowsPhone = windowsPhoneFactory.createMobilePhone();
if (androidPhone != null) androidPhone.call("13900000000");
if (iPhone != null) iPhone.call("13900000000");
if (windowsPhone != null) windowsPhone.call("13900000000");
}
}
// 同事B的代碼
/** 創(chuàng)建工廠類(lèi)的實(shí)現(xiàn)類(lèi) */
public class AndroidPhoneFactory implements PhoneFactory {
public MobilePhone createMobilePhone() {
return new AndroidPhone();
}
}
public IPhoneFactory implements PhoneFactory {
public static MobilePhone createMobilePhone() {
return new IPhone();
}
}
public WindowsPhoneFactory implements PhoneFactory {
public static MobilePhone createMobilePhone() {
return new WindowsPhone();
}
}
/** 手機(jī)的實(shí)現(xiàn)類(lèi) */
public class AndroidPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use AndroidPhone");
}
}
public class IPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use iPhone");
}
}
public class WindowsPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use WindowsPhone");
}
}
作用:不用像普通工廠模式那樣總要通過(guò)傳參來(lái)告訴工廠類(lèi)我要什么產(chǎn)品了,萬(wàn)一參數(shù)寫(xiě)錯(cuò)一個(gè)字母呢晃择?是吧冀值,現(xiàn)在需要哪種產(chǎn)品就直接找生產(chǎn)那種產(chǎn)品的工廠即可。
3宫屠、抽象工廠模式
描述:前邊講的工廠方法模式是有多個(gè)工廠列疗,每個(gè)工廠只生產(chǎn)一種產(chǎn)品。而抽象工廠模式是有一個(gè)工廠接口浪蹂,但是這工廠不止能生產(chǎn)一種產(chǎn)品抵栈,而是能生產(chǎn)多個(gè)產(chǎn)品。
作用:如果只是從抽象工廠模式自身出發(fā)來(lái)解釋還是比難理解的坤次,要了解抽象工廠模式其實(shí)最好是跟前邊兩種對(duì)比古劲,你就會(huì)明白為什么要使用抽象工廠模式了。
(1)最開(kāi)始的簡(jiǎn)單工廠模式的缺點(diǎn)是你總要通過(guò)傳參來(lái)創(chuàng)建對(duì)象缰猴,傳參有點(diǎn)麻煩产艾,參數(shù)也有可能傳錯(cuò);
(2)工廠方法模式的缺點(diǎn)是你要先定義一大堆工廠接口的對(duì)象,用每個(gè)工廠接口對(duì)象創(chuàng)建一種產(chǎn)品闷堡,那么定義一大堆對(duì)象隘膘,然后去管理這一大堆對(duì)象顯然也是比較麻煩的事情;
(3)如果我即不想通過(guò)傳參創(chuàng)建對(duì)象杠览,又不想創(chuàng)建一大堆工廠對(duì)象要怎么做呢弯菊?并且這個(gè)工廠在其它同事還沒(méi)有做出來(lái)時(shí)先以接口形式存在,讓我們可以提前使用踱阿、并且將來(lái)可以隨意替換它的實(shí)現(xiàn)類(lèi)呢管钳?抽象工廠模式就是針對(duì)這一點(diǎn)對(duì)工廠方法模式做了改進(jìn)。
// 同事A的代碼
/** 定義一個(gè)“移動(dòng)電話(huà)”接口 */
public interface MobilePhone {
public void call(String phoneNumber);
}
/** 創(chuàng)建工廠類(lèi)接口 */
public interface PhoneFactory {
public static MobilePhone createAndroidPhone();
public static MobilePhone createIPhone();
public static MobilePhone createWindowsPhone();
}
/** 主程序中調(diào)用 */
public class MyTest {
private MobilePhone androidPhone;
private MobilePhone iPhone;
private MobilePhone windowsPhone;
// 現(xiàn)在只需要?jiǎng)?chuàng)建一個(gè)工廠對(duì)象
private PhoneFactory phoneFactory;
public static void main(String[] args) {
// 將來(lái)需求改變時(shí)可以隨意替換工廠類(lèi)的實(shí)現(xiàn)類(lèi)软舌,其它代碼不用改
phoneFactory = new phoneFactoryImpl();
// 不需要傳參就能創(chuàng)建對(duì)象
androidPhone = phoneFactory.createAndroidPhone();
iPhone = phoneFactory.createIPhone();
windowsPhone = phoneFactory.createWindowsPhone();
if (androidPhone != null) androidPhone.call("13900000000");
if (iPhone != null) iPhone.call("13900000000");
if (windowsPhone != null) windowsPhone.call("13900000000");
}
}
// 同事B的代碼
/** 創(chuàng)建工廠類(lèi)的實(shí)現(xiàn)類(lèi) */
public class PhoneFactoryImpl implements PhoneFactory {
public static MobilePhone createAndroidPhone() {
return new AndroidPhone();
}
public static MobilePhone createIPhone() {
return new IPhone();
}
public static MobilePhone createWindowsPhone() {
return new WindowsPhone();
}
}
/** 手機(jī)的實(shí)現(xiàn)類(lèi) */
public class AndroidPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use AndroidPhone");
}
}
public class IPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use iPhone");
}
}
public class WindowsPhone implements MobilePhone {
public void call(String phoneNumber) {
System.out.println("Dial phoneNumber " + phoneNumber + "use WindowsPhone");
}
}
缺點(diǎn):等你的同事寫(xiě)好工廠類(lèi)接口的實(shí)現(xiàn)類(lèi)之后才漆,你還是要回過(guò)頭來(lái)改你當(dāng)初的代碼,把他的實(shí)現(xiàn)類(lèi)賦給你的接口葫隙,也就是說(shuō)還是無(wú)法實(shí)現(xiàn)完全的解耦栽烂。
好文章引用
有感于四人幫那套書(shū)對(duì)廣大的編程人員誤導(dǎo)之嚴(yán)重, 決定寫(xiě)一個(gè)小系列,專(zhuān)門(mén)說(shuō)這個(gè). 此文權(quán)當(dāng)?shù)谝黄? 為什么工廠模式是不必要的?
做一件事之前,要想的不是怎么做,而是為什么要做,工廠到底要解決什么問(wèn)題?
其實(shí)歸根結(jié)底就是為了不必在創(chuàng)建時(shí)顯式指定要?jiǎng)?chuàng)建的類(lèi)型,因?yàn)閹讉€(gè)工廠其實(shí)本質(zhì)是一樣的, 抽象工廠是完整的, 普通工廠是化簡(jiǎn)了, 簡(jiǎn)單工廠方法又再化簡(jiǎn)一次. 如果連抽象工廠這個(gè)最復(fù)雜的都是沒(méi)必要存在的, 那么另外兩個(gè)就更沒(méi)存在的意義了.所以這里就對(duì)著抽象工廠來(lái)開(kāi)刀.
按照四人幫最早原文說(shuō)的抽象工廠存在的意義是為了: Create related objects without specifying concrete class at point of creation.
那我們來(lái)看看這件事到底需要不需要引入"工廠". 典型的工廠模式的用例(不要再用工廠生產(chǎn)自行車(chē)和汽車(chē)做例子了....這是在偷概念, 讓factory同時(shí)扮演業(yè)務(wù)對(duì)象和程序引入的不必要的噪音,這掩蓋了問(wèn)題) 做一個(gè)跨平臺(tái)的UI庫(kù), 支持Windows,Mac,Linux等很多系統(tǒng), 有按鈕,滾動(dòng)條等很多不同控件. 這是典型的抽象工廠案例,按照四人幫的思路, 應(yīng)該有3個(gè)工廠分別給這3個(gè)平臺(tái), 如果有第4個(gè)平臺(tái)就再加一個(gè)工廠, 然后還要一個(gè)抽象的工廠的父類(lèi), 用來(lái)給調(diào)用方使用(這樣調(diào)用方就不需要關(guān)心到底現(xiàn)在在哪個(gè)系統(tǒng)), 然后每個(gè)平臺(tái)有自己的控件的基類(lèi), 比如WindowsControl, LinuxCintrol....這些控件基類(lèi)又是從一個(gè)通用的控件類(lèi)繼承, 然后不同的滾動(dòng)條,按鈕什么的再?gòu)母髯云脚_(tái)的Control繼承... ..這樣就形成龐大的一大堆類(lèi)和對(duì)象...
對(duì)于同一個(gè)控件, 比如button,需要一堆各種平臺(tái)的工廠, 還有一堆各種平臺(tái)各自的按鈕. 各種平臺(tái)各自的按鈕是客觀上業(yè)務(wù)需要(畢竟Windows和Linux顯然有不同底層接口..這種分別是客觀存在的), 但是那些Factory真的有必要存在么?
為什么我們不能讓控件類(lèi)自己來(lái)管自己的創(chuàng)建過(guò)程呢?
也許有人說(shuō), 我們剛才要的不就是要?jiǎng)?chuàng)建的時(shí)候不需要知道創(chuàng)建的是什么嗎, 如果用控件類(lèi)自己來(lái)直接new,那就必須要確定要new的是什么類(lèi). 而抽象類(lèi)是無(wú)法new出來(lái)對(duì)象的.
等等, 為什么只能new,不能像工廠那樣 create ?
比如 Button 類(lèi)(這是抽象類(lèi))
public abstract class Button
{
public static Button CreateButton(......)
{
//這里可以跟工廠里一樣,根據(jù)參數(shù)或者配置,new出不同的子類(lèi).
}
}
public class WindowsButton : Button {...}
public class LinuxButton : Button {...}
//客戶(hù)端調(diào)用跟使用工廠沒(méi)有區(qū)別...對(duì)應(yīng)于抽象工廠的每個(gè)子工廠,都這么做
最終結(jié)果就是少了一大堆工廠類(lèi), 但是目的一樣達(dá)成, 對(duì)維護(hù)沒(méi)有什么影響,因?yàn)槟阍黾右环N控件要干的事情是一樣的,只是把改工廠變成改父類(lèi)了,而且改的一樣是一處地方而已.
對(duì)于新添加一個(gè)平臺(tái), 可以比抽象工廠少加一個(gè)類(lèi).
類(lèi)更少,代碼更少,出bug的機(jī)會(huì)也就更少, 而且代碼更加內(nèi)聚, 本來(lái)問(wèn)題里面就沒(méi)工廠什么事情. 代碼應(yīng)該只表達(dá)需要表達(dá)的邏輯, 任何額外的附加都是應(yīng)該避免的(但是有時(shí)候因?yàn)榫幊陶Z(yǔ)言不夠強(qiáng)大而無(wú)法避免).
事實(shí)上, "在創(chuàng)建對(duì)象時(shí)不需要指定具體創(chuàng)建的類(lèi)",這個(gè)需求如果是很罕見(jiàn)的話(huà), 那么不應(yīng)該作為一種設(shè)計(jì)模式,因?yàn)槟J綉?yīng)該是常見(jiàn)的可復(fù)用的模板和方法. 反過(guò)來(lái)如果這是一件常見(jiàn)的事情, 那么就應(yīng)該是語(yǔ)言的 編譯器 要做的事情, 如果一門(mén)語(yǔ)言, 要做這件事需求求助于 像 抽象工廠這樣復(fù)雜的結(jié)構(gòu),(這個(gè)結(jié)構(gòu)是實(shí)現(xiàn)技術(shù)疊加給它的,并不是問(wèn)題本身有的) 那只能說(shuō)明這門(mén)語(yǔ)言的設(shè)計(jì)者語(yǔ)法設(shè)計(jì)得有問(wèn)題,不夠完善,以至于程序員遇到一個(gè)"常見(jiàn)"的問(wèn)題的時(shí)候, 需要 自己寫(xiě)一大堆類(lèi)和代碼來(lái) 完成本該編譯器完成的工作(也就是程序員當(dāng)人肉編譯器了....)
C#的語(yǔ)法設(shè)計(jì)上允許一個(gè)抽象類(lèi)有靜態(tài)的方法,這就讓factory不必要存在了.
PS: 如果有人要說(shuō),萬(wàn)一父類(lèi)是系統(tǒng)庫(kù)里面的,我改不了呢? 那不就需要個(gè)工廠了嗎? 其實(shí)依然不需要工廠, 不過(guò),這就涉及到另外一個(gè)設(shè)計(jì)模式遇到的問(wèn)題, 你需要給一個(gè)類(lèi)添加方法, 而這個(gè)類(lèi)的代碼你無(wú)法修改. 四人幫的書(shū)里用的方法是裝飾器. 這依然可以是個(gè)不必要的的模式..本文后面會(huì)簡(jiǎn)單說(shuō)一些不需要的模式.
事實(shí)上, 四人幫寫(xiě)書(shū)之前, 已經(jīng)有 設(shè)計(jì)模式 這個(gè)詞, 當(dāng)時(shí)的含義跟現(xiàn)在完全不同. 是很泛化的, 比如匯編語(yǔ)言不支持函數(shù)調(diào)用語(yǔ)法, 于是形成了模式, 就是你要進(jìn)入一個(gè)子程序, 就把你要傳的數(shù)據(jù)(參數(shù)) 按順序 push 入棧, 然后再進(jìn)入子程序, 子程序里如果還有子程序, 再里面再push, 然后每退出一層就pop出來(lái)... 這就是最早的模式, 但是當(dāng)像C這樣的支持函數(shù)調(diào)用的語(yǔ)言里, 這個(gè)模式是不需要的. 因?yàn)槿霔3鰲5牟僮? 編譯器幫你生成了.
其實(shí)所有的所謂的模式, 都是因?yàn)檎Z(yǔ)言設(shè)計(jì)的不完善, 才使得程序員需要使用 "模式" 來(lái)解決問(wèn)題, (另外一個(gè)角度,因?yàn)檎Z(yǔ)法完美的語(yǔ)言可遇不可求,所以設(shè)計(jì)模式一直流行著...). 語(yǔ)言語(yǔ)法越強(qiáng)大,模式越不需要.
再舉個(gè)例子,單件模式, 為了產(chǎn)生一個(gè)全局的訪(fǎng)問(wèn)點(diǎn). 其實(shí)產(chǎn)生就產(chǎn)生吧,為什么需要搞個(gè)模式呢? 因?yàn)镃++不能保證產(chǎn)生過(guò)程是線(xiàn)程安全的, 如果兩個(gè)線(xiàn)程同時(shí)進(jìn)入, 有可能會(huì)產(chǎn)生出兩個(gè)對(duì)象,這樣"全局訪(fǎng)問(wèn)點(diǎn)"的目的就落空了, 因此需要使用加鎖的機(jī)制, 加鎖影響性能, 因?yàn)槠鋵?shí)創(chuàng)建只有第一次的時(shí)候需要發(fā)生以后都是讀取訪(fǎng)問(wèn)應(yīng)該是不需要鎖的, 于是, 在外面加了個(gè)if 來(lái)跳過(guò)鎖,但是又因?yàn)镃++里這兩個(gè)沒(méi)法保證原子性,于是又需要使用 " 雙檢鎖" 策略...于是一個(gè)簡(jiǎn)單的new操作就變成了 3層嵌套...那么有必要把這個(gè)邏輯單獨(dú)抽出來(lái), 于是單件模式就誕生了. 在C#里這一系列問(wèn)題都不復(fù)存在, 雖然可以模仿C++寫(xiě)出一樣的代碼,但是你寫(xiě)來(lái)干嘛? 如果原始目的是要全局訪(fǎng)問(wèn)點(diǎn), 靜態(tài)類(lèi)已經(jīng)完全保證了全局訪(fǎng)問(wèn)點(diǎn)并絕不會(huì)創(chuàng)建出第2個(gè)....
還有剛才上面說(shuō)的裝飾器模式, 裝飾器的目的是什么? C#有了 擴(kuò)展方法, 還要裝飾器干什么?
最后,C#語(yǔ)法經(jīng)過(guò)這些年微軟式的快速更新?lián)Q代,已經(jīng)很復(fù)雜很強(qiáng)大了, 但是它不是完美的, 它無(wú)法完整地解決上面說(shuō)的那幾個(gè)...比如擴(kuò)展方法不允許實(shí)現(xiàn)接口(也許以后哪個(gè)版本可以...), 所以上面那種情況沒(méi)法通過(guò)擴(kuò)展方法去解決工廠的問(wèn)題.... 靜態(tài)類(lèi)因?yàn)槔^承的問(wèn)題也帶來(lái)一些制約...
不過(guò),確實(shí)有語(yǔ)言完整地解決這些問(wèn)題, 比如 Clojure語(yǔ)言的 "協(xié)議" 語(yǔ)法(跟C#的接口類(lèi)似, 但是不需要在類(lèi)定義的時(shí)候指定這個(gè)類(lèi)實(shí)現(xiàn)什么協(xié)議..., 可以在以后任何時(shí)候需要的話(huà)給一個(gè)類(lèi)或者對(duì)象附加一個(gè)協(xié)議并實(shí)現(xiàn)上去....并且可以不破壞封裝性, 而且只在特定模塊可見(jiàn)....用C#的話(huà)說(shuō)就是你可以給String加上一個(gè)Interface并實(shí)現(xiàn)那些方法,但是這個(gè)實(shí)現(xiàn)只對(duì)某個(gè)namespace 可見(jiàn), 所以你不怕會(huì)影響微軟的那些使用String類(lèi)的方法,因?yàn)閷?duì)他們來(lái)說(shuō)String并沒(méi)有這些方法和接口...他們?cè)诟悴煌膎amespace里 )完整解決了裝飾器模式的問(wèn)題.
至于上面那個(gè)工廠的問(wèn)題, 很多動(dòng)態(tài)語(yǔ)言比如javascript或者lisp等,因?yàn)閯?dòng)態(tài)的特性, 可以完全避免, 比如某些動(dòng)態(tài)語(yǔ)言可以直接 make(抽象基類(lèi),參數(shù)1,參數(shù)2) 來(lái)構(gòu)建出子類(lèi)對(duì)象而不需要指定子類(lèi), 那么工廠相關(guān)方法就真的完全不需要了...
在Dylan或者Lisp里, 四人幫23種設(shè)計(jì)模式里面完全不需要的模式達(dá)到有16種之多...所以設(shè)計(jì)模式其實(shí)應(yīng)該跟語(yǔ)言相關(guān)的, 不是說(shuō)你把C++的東西改下語(yǔ)法就是java的就是C#的,很多用其他語(yǔ)言寫(xiě)的設(shè)計(jì)模式的書(shū),就是照把四人幫的內(nèi)容照著搬一次然后代碼改成XXX語(yǔ)言, 這么些年下去,讓很多人迷失在設(shè)計(jì)模式里而把簡(jiǎn)單的東西復(fù)雜化.
寫(xiě)了很多年代碼以后,
11年前的一天, 我第一次知道有設(shè)計(jì)模式這種東西的時(shí)候,覺(jué)得太無(wú)聊了,把東西弄復(fù)雜了.
9年前在一個(gè)大型項(xiàng)目中因?yàn)樾枨笞兏a一團(tuán)糟的時(shí)候,我才終于知道設(shè)計(jì)模式是干什么的,有什么用,于是開(kāi)始研究和迷戀設(shè)計(jì)模式.
到了大約5年前,我已經(jīng)可以不管什么模式不模式, 隨便寫(xiě)一段代碼就帶著這種或那種模式的變體,組合各種模式來(lái)創(chuàng)建出所謂 柔軟的代碼. 手中無(wú)劍而心中有劍.
但是后來(lái)在stackoverflow我認(rèn)識(shí)了一個(gè)網(wǎng)友,一個(gè)老外,他說(shuō)設(shè)計(jì)模式是語(yǔ)言的BUG, 這些BUG需要人肉修復(fù),于是就有了模式. 我仔細(xì)思考了很久, 越來(lái)越發(fā)現(xiàn)他說(shuō)的有道理. 當(dāng)我因?yàn)楣ぷ餍枰佑|了LISP系語(yǔ)言以后, 發(fā)現(xiàn)那個(gè)世界里沒(méi)人把那23種當(dāng)事情, 而解決那些問(wèn)題的代碼都是又短又漂亮而優(yōu)雅.
這個(gè)文章是突然看見(jiàn)那個(gè)上面鏈接的文章而有感而發(fā),沒(méi)打草稿,一氣敲出,所以可能有手誤的地方,.... 而且我此文是針對(duì)的"設(shè)計(jì)模式" 這個(gè)東西,不是針對(duì)連接所指的文章,那個(gè)文章寫(xiě)的還是挺細(xì)致的.......
剛才發(fā)現(xiàn)我上篇博客還是在8年前,多年未寫(xiě),文字有些混亂, 歡迎有疑惑或異議者留言探討.