初識設計模式

每一個模式描述了一個在我們周圍不斷重復發(fā)生的問題,以及該問題的解決方案的核心.這樣,你就能一次又一次地使用該方法而不必做重復勞動
by Christopher Alexander

從目前的編碼過程中,可能我的狀態(tài)就是比較注重功能的實現(xiàn)轧膘,然而面對其他的比如對象之間的耦合關系什么的基本沒有考慮到推掸,雖然使用著面向對象的語言罪塔,做的好像不是面向對象的事情懊昨。學習設計模式能讓人加深對面向對象編程的理解玷氏,有時候會讓人有一種醍醐灌頂?shù)母杏X元旬。然而設計模式雖好岂昭,但不要沉迷其中無法自拔,還是得有自己的思考车伞。好了說了些廢話择懂,正文開始了。

說到設計模式就不得不提一本書GOF設計模式:可復用面向對象軟件的基礎另玖,我們把目光鎖定在后面的解釋困曙,可復用,正如開頭所引用的話谦去,模式的最終目標就是復用慷丽,放在軟件開發(fā)中也是如此,一個臃腫的類體系是人們不愿意看到的鳄哭。另外要糊,設計模式提供了一種不同的思維方式,它使得我們跳出了事物本身的局限妆丘,去考慮更加本質的東西锄俄,首先就從java的面向對象說起局劲,這里有兩種不同的思維方式

  • 底層思維:向下,如何把握機器底層奶赠,我們是從微觀的角度去理解對象構造鱼填,這涉及到了很多方面的知識:
  • 語言構造
  • 編譯轉換
  • 內存模型
  • 運行時機制
  • 抽象思維:向上,這種思維方式在設計領域的時候用的比較多毅戈,拋開一些編碼和編譯的細節(jié)苹丸,主要關心如何將我們周圍的世界抽象為程序代碼,這個過程就關系著設計最終的好壞苇经,代碼的品質:
  • 面向對象
  • 組件封裝
  • 設計模式
  • 架構模式
    在抽象思維里赘理,上面的方式是基本互通的,只是表達方式不同扇单。

抽象思維是建立在比較升入理解了底層思維的基礎上的感憾,面向對象的三大特性:封裝(隱藏內部實現(xiàn)),繼承(復用現(xiàn)有代碼)令花,多態(tài)(改寫對象行為)阻桅,這三大特性在設計模式里十分重要,在設計模式里兼都,理解靈活多變的利用這三大特性來描述現(xiàn)實世界嫂沉,也就理解了設計模式這樣設計的原因和意義所在。

由于個人水平比較菜扮碧,所以現(xiàn)在也還沒有參與過什么項目趟章,然而耳聞過。為什么說軟件設計很復雜慎王,因為在項目開展的過程中蚓土,會有永運猜不透想法的客戶的需求變化,你不得不接受的團隊成員的流動赖淤,技術平臺日新月異的更新等一系列不可控因素蜀漆,然而在軟件設計的初期要盡可能的把這些變化考慮進去,難不難咱旱,當然難确丢。需不需要去解決,當然需要吐限!怎么解決鲜侥?當人們遇到比較復雜的問題的時候,都這樣做诸典,我也這樣做:

  • 分解
  • 人們面向復雜性有一個常見的做法:即分而治之描函,將大問題分解問哦多個小問題,將復雜問題分解為多個簡單問題,這個方法在一些場景里是非常適用的舀寓,比如算法里分治法的使用益缠。不過在面對復雜性多樣變化的場景時,就不是那么的可愛了基公,首先大問題的劃分就很難統(tǒng)一,因為未來的變化總是未知的宋欺,掌握所有的情況是不可能的轰豆。
  • 抽象
  • 更高層次來講,人們處理復雜性有一個通用的技術齿诞,即抽象酸休。由于不能掌握全部的復雜對象,我們選擇忽略它的非本質細節(jié)祷杈,而去處理泛化和理想化了的對象模型斑司。這有點哲學的味道了,關注本質但汞。

比如我們有兩個圖形類:

//直線類
class Line {
    public int startX;
    public int startY;
    public int endX;
    public int endY;

    public Line(int startX, int startY, int endX, int endY) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;
    }
}

//矩形類
class Rect {
    public int left;
    public int top;
    public int right;
    public int bottom;

    public Rect(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }
}

然后在MainActivity中分別實現(xiàn)宿刮,不需要在意功能,就只關心使用的地方

  Vector<Line> lineVector = new Vector<Line>();
  Vector<Rect> rectVector = new Vector<Rect>();

     if (lineRadio.isChecked()) {
                    lineVector.add(new Line(startPoint.x,
                            startPoint.y,
                            endPoint.x,
                            endPoint.y));
                } else if (rectRadio.isChecked()) {
                    rectVector.add(new Rect(startPoint.x,
                            startPoint.y,
                            endPoint.x,
                            endPoint.y));
                }
                //更改...
                else if(...){

                }
          }
            for (int i = 0; i < lineVector.size(); i++) {

                canvas.drawLine(lineVector.get(i).startX,
                        lineVector.get(i).startY,
                        lineVector.get(i).endX,
                        lineVector.get(i).endY,
                        paint);
            }

            for (int i = 0; i < rectVector.size(); i++) {

                canvas.drawRect(rectVector.get(i).left,
                        rectVector.get(i).top,
                        rectVector.get(i).right,
                        rectVector.get(i).bottom,
                        paint);

            }

上面第一段代碼是先生成每一個圖形的Vector私蕾,然后分別add僵缺,下面的for循環(huán)可以理解為輪詢每一個不同的Vector對象,然后畫出圖形踩叭。當代碼寫完了磕潮,突然想起,哎呀忘記Circle了,于是首先得在寫出一個Circle的類,然后new一個Circle的Vector數(shù)組尔崔,接著在add處也要修改凿将,最后還要增加一個for循環(huán),忘記一個就要更改4處沪猴,是不是很復雜,而且當代碼多的時候,更改的出錯率會增多戏罢,這是很危險的。
如果我們從另外一方面脚囊,或者說抽象出來龟糕,這些都是屬于圖形,那我們定義一個抽象圖形類:

//形狀基類
abstract class  Shape {

    abstract void draw(Canvas canvas, Paint paint);

}

然其他無論什么圖形都繼承它悔耘。接著生成了一個Vector數(shù)組:

Vector<Shape> shapeVector = new Vector<Shape>();

而add時讲岁,增加具體圖形的數(shù)據(jù),for循環(huán)也是它,這樣不管是什么圖形缓艳,都可以繪制出來校摩,不用單獨去考慮:

      for (int i = 0; i < shapeVector.size(); i++) {

                shapeVector.get(i).draw(canvas, paint);

            }

如果需求變更了,增加了圖形阶淘,我們只需要繼承Shape寫一個實體類衙吩,再在add處增加新圖形的add方法,其他的都不會變化溪窒。相對于第一種坤塞,當需求變化發(fā)生的時候,很多的代碼得以復用澈蚌,而不用像第一種手忙腳亂摹芙,這里那里修改,所以相對于分解思維模式宛瞄,抽象模式的優(yōu)勢就體現(xiàn)出來--復用浮禾。

所以用了java語言,并不一定擁有了抽象的設計思維份汗,說的就是我盈电。

重新認識面向對象:

  • 理解隔離變化
  • 從宏觀層面來看,面向對象的構建方式更能使用軟件的變化杯活,比如上面的例子挣轨,能將變化所帶來的影響減為最小
  • 各司其職
  • 從微觀層面,面向對象的方式更強調各個類的責任
  • 由于需求變化導致的新增類型不應該影響原來的類型的實現(xiàn)-就是叫做所謂各負其責轩猩。
  • 對象深入
  • 從語言實現(xiàn)層面來說卷扮,對象封裝了代碼和數(shù)據(jù)
  • 從規(guī)格層面來講,對象是一系列可被使用的公共接口
  • 從概率層面講均践,對象是某種擁有責任的抽象

面向對象設計原則:

  1. 依賴倒置原則(DIP)
  • 高層模塊(穩(wěn)定)不應該依賴低層模塊(變化)晤锹,二者都應該依賴于抽象(穩(wěn)定)
  • 抽象(穩(wěn)定)不應該依賴與實現(xiàn)細節(jié)(變化),實現(xiàn)細節(jié)應該依賴于抽象 (穩(wěn)定)
  1. 開放封閉原則(OCP)
  • 對擴展開發(fā)彤委,對更改封閉
  • 類模塊應該是可擴展鞭铆,但是不可修改
  1. 單一職責原則(SRP)
  • 一個類應該僅有一個引起它變化的原因
  • 變化的方向隱含這類的責任。
  1. Liskov替換原則(LSP)
  • 子類必須能夠替換他們的基類
  • 繼承表達類型抽象
  1. 接口隔離原則(ISP)
  • 不應該強迫客戶程序依賴他們不用的方法
  • 接口應該小而完備
  1. 優(yōu)先使用對象組合焦影,而不是類繼承
  • 類繼承通常為"白箱復用"车遂,對象組合通常為"黑箱復用"
  • 類繼承在某種程度上破壞了封裝性,子類父類耦合度高
  • 而對象組合則只要求被組合的對象具有良好定義的接口斯辰,耦合度低
  1. 封裝變化點
  • 使用封裝來創(chuàng)建對象之間的分界層舶担,讓設計者可以在分界層的一側進行修改,而不會對另一側產生不良的影響彬呻,從而實現(xiàn)層次間的松耦合
  1. 針對接口編程衣陶,而不是針對實現(xiàn)編程
  • 不將變量類型聲明為某個特定的具體類柄瑰,而是聲明為某個接口
  • 客戶程序無需獲知對象的具體類型,只需要知道對象所具有的接口剪况。
  • 減少系統(tǒng)中各部分的依賴關系教沾,從而實現(xiàn)“高內聚,松耦合”的類型設計方案

老師舉了兩個例子译断,一個是秦統(tǒng)一六國之后授翻,統(tǒng)一貨幣統(tǒng)一度量衡,從軟件開發(fā)的角度來說就是統(tǒng)一了接口孙咪,并且使其規(guī)范化堪唐。再一個是畢升的活字印刷術,它的發(fā)明之所以推進了人類文明的發(fā)展该贾,是因為首先復用了每個漢字,按需所用捌臊,不需要像雕版印刷一樣來一篇文章刻一次版杨蛋,其次規(guī)定了每個字模的大小規(guī)格,畢升就是松耦合大師理澎。通過這個感性的認識逞力,就會體會到接口規(guī)范化對于行業(yè)的貢獻。

以上糠爬,歡迎指正寇荧。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市执隧,隨后出現(xiàn)的幾起案子揩抡,更是在濱河造成了極大的恐慌,老刑警劉巖镀琉,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峦嗤,死亡現(xiàn)場離奇詭異,居然都是意外死亡屋摔,警方通過查閱死者的電腦和手機烁设,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钓试,“玉大人装黑,你說我怎么就攤上這事」” “怎么了恋谭?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長挽鞠。 經常有香客問我箕别,道長铜幽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任串稀,我火速辦了婚禮除抛,結果婚禮上,老公的妹妹穿的比我還像新娘母截。我一直安慰自己到忽,他們只是感情好,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布清寇。 她就那樣靜靜地躺著喘漏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪华烟。 梳的紋絲不亂的頭發(fā)上翩迈,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音盔夜,去河邊找鬼负饲。 笑死,一個胖子當著我的面吹牛喂链,可吹牛的內容都是我干的返十。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼椭微,長吁一口氣:“原來是場噩夢啊……” “哼洞坑!你這毒婦竟也來了?” 一聲冷哼從身側響起蝇率,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤迟杂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后本慕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢慌,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年间狂,在試婚紗的時候發(fā)現(xiàn)自己被綠了攻泼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡鉴象,死狀恐怖忙菠,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情纺弊,我是刑警寧澤牛欢,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站淆游,受9級特大地震影響傍睹,放射性物質發(fā)生泄漏隔盛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一拾稳、第九天 我趴在偏房一處隱蔽的房頂上張望吮炕。 院中可真熱鬧,春花似錦访得、人聲如沸龙亲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鳄炉。三九已至,卻和暖如春搜骡,著一層夾襖步出監(jiān)牢的瞬間拂盯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工记靡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谈竿,地道東北人。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓簸呈,卻偏偏與公主長得像榕订,于是被迫代替她去往敵國和親店茶。 傳聞我的和親對象是個殘疾皇子蜕便,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容

  • 設計模式匯總 一、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用贩幻、多...
    MinoyJet閱讀 3,919評論 1 15
  • 設計模式基本原則 開放-封閉原則(OCP)轿腺,是說軟件實體(類、模塊丛楚、函數(shù)等等)應該可以拓展族壳,但是不可修改。開-閉原...
    西山薄涼閱讀 3,760評論 3 13
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,730評論 25 707
  • 天貓電商指標拆解 葉郁趣些、賴慧詩仿荆、瓦力、小陌陌坏平、蘇蘇拢操、月時、陳N次方舶替、白海波令境、茜茜、jalucky顾瞪、宋小錯舔庶、睿風抛蚁、H...
    三節(jié)課班主任閱讀 354評論 0 0
  • 談到乞討說個事兒。 15年我們騎行進入川藏之后就經常遇到一些藏族小孩兒在路上向我們索要糖果惕橙,我還遇到一次一個小孩試...
    最可愛的靖靖閱讀 250評論 1 1