你真的理解設(shè)計(jì)模式嗎?

序言

做開(kāi)發(fā)久一點(diǎn)的都知道設(shè)計(jì)模式名眉,你很多人看了很多書(shū)籍和文章粟矿,但因用了設(shè)計(jì)模式而收益匪淺的人可能不是很多。這又是為什么呢损拢?

下面我們以工廠模式為切入點(diǎn)陌粹,循序漸進(jìn)的來(lái)理解設(shè)計(jì)模式

  1. what is it?福压?
  2. How do we use it掏秩?
  3. 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ě),文字有些混亂, 歡迎有疑惑或異議者留言探討.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市恋脚,隨后出現(xiàn)的幾起案子腺办,更是在濱河造成了極大的恐慌,老刑警劉巖糟描,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件怀喉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡船响,警方通過(guò)查閱死者的電腦和手機(jī)躬拢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)见间,“玉大人聊闯,你說(shuō)我怎么就攤上這事∶姿撸” “怎么了菱蔬?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)史侣。 經(jīng)常有香客問(wèn)我拴泌,道長(zhǎng),這世上最難降的妖魔是什么惊橱? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任蚪腐,我火速辦了婚禮,結(jié)果婚禮上税朴,老公的妹妹穿的比我還像新娘回季。我一直安慰自己家制,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布泡一。 她就那樣靜靜地躺著慰丛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瘾杭。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,031評(píng)論 1 285
  • 那天哪亿,我揣著相機(jī)與錄音粥烁,去河邊找鬼。 笑死蝇棉,一個(gè)胖子當(dāng)著我的面吹牛讨阻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播篡殷,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钝吮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了板辽?” 一聲冷哼從身側(cè)響起奇瘦,我...
    開(kāi)封第一講書(shū)人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎劲弦,沒(méi)想到半個(gè)月后耳标,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邑跪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年次坡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片画畅。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砸琅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出轴踱,到底是詐尸還是另有隱情症脂,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布寇僧,位于F島的核電站摊腋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏嘁傀。R本人自食惡果不足惜兴蒸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望细办。 院中可真熱鬧橙凳,春花似錦蕾殴、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至坚踩,卻和暖如春荡灾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背瞬铸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工批幌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人嗓节。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓荧缘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拦宣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子截粗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容