物件導向基本原則

.NET西安發表於2021-01-31

一、前言

  專案中使用 Design Pattern 越多越好?  哪種 Pattern 比較重要? 需要學習哪些 Pattern ?

  對於入門者來說,直接上手學習 Design Pattern 可能會產生很多困惑,認為程式設計很難。好比修煉神功祕籍,首先得會基本功曉原理;其次才能進階修煉高階術法,除非有高人指點,否則輕則自廢武功重則走火入魔。

  其實不必, 沒有 Design Pattern 也可以寫出 “Good Code”。應用程式首先是用來解決問題,不要過分關心 Design Pattern 沒有必要為了 Pattern 而 Pattern;但軟體開發領域 “Design Pattern” 又很重要,怎麼辦? 有個建議可以從 “SOLID、DRY” 開始,物件導向程式設計的基本原則。

  

  物件導向原則 & Design Pattern 兩者區別:

  物件導向基本原則:是一種指導規範,應該怎麼幹,告訴開發者你應該遵循這種規範。 

  Design Pattern :是遵循程式設計規範解決特定問題的具體實踐。

二、物件導向基本原則

  SOLID 由美國軟體工程師 Robert C. Martin 總結提出 。維基百科 :https://en.wikipedia.org/wiki/SOLID 。

  SOLID: 

  S - <Single-responsiblity Principle> 單一職責原則 

  O - <Open-closed Principle>開閉原則

  L -<Liskov Substitution Principle>里氏替換原則

  I - <Interface Segregation Principle>介面隔離原則

  D -<Dependency Inversion Principle>依賴倒置原則

  DRY: < Don't repeat yourself> 不要重複自己原則

 

  1、Single-responsiblity Principle

  單一職責描述:一個類只有一個用途,沒有兩個用途,沒有三個用途。

  好比假設汽車的剎車、油門踏板沒有分開設計,被設計成 剎車油門踏板,或者把離合也加進去。想象一下,使用的時候垂直踏下去是剎車,向左偏向下踏是加油,向右向下踏是離合;這樣設計的後果 不僅考驗駕車者的車技,甚者交通事故率大概率會直線上升。

 

  實踐中如果發現類規模越來越大職責越來越多,此時開始著手重構它。

  實踐中如果發現一個方法,隨著業務變動引數越來越多、方法體越來越臃腫、乾的事情越來越多,最顯而易見的是 If else 語句變多,此時著手重構它。

 

  題外:分析具體情況,引數多是不是也可以重構為使用一個物件傳遞,If else  語句多使用 “表驅動法”  、Factory Pattern 解決。

 

  2、Open-closed Principle

  開閉原則描述:軟體實體應該對擴充套件開放,對修改關閉。

  現在各種計步手環特別火,公司安排你做一個整合平臺,展示跑步線路。該怎麼做?

  假設你是一個軟體工程師,加班太多以至於沒有時間打掃房間,你僱傭了一個王阿姨打掃房間,一直相安無事,突然有一天王阿姨家有事回家了。剛好這一天心儀的女同事提出去你家做客,而你焦慮房間亂沒人打掃。 有了這次經驗,你可能會找一個家政公司幫你打掃房間,不用關心王阿姨請假或者有事。 你稱之為 “中介者原則”,依賴中介去打掃衛生,而不是依賴某個阿姨,阿姨會有事,中介公司不打樣。

  實踐中我們依賴抽象不依賴實現,如果發現依賴實現,此時重構它。

  實踐中如果寫 “Hello World” ,我不會考慮任何原則或者模式。

  現在開始寫線路解析程式,遵循 “中介者原則”  定義一個“抽象解析中介” 然後依賴並實現它。 以後不管再來幾個手環廠家,我們都可以做擴充套件,而不用修改已有的解析程式。

 

  3、Liskov Substitution Principle

  里氏替換原則描述:子類或者派生類可以替代其基類或父類,用子類例項替代父類例項不產生負面影響。

  最直觀的例子就是,你不能用黃種人作為有色人種或者白色人種的祖先,或者其他人種的祖先作為黃種人的祖先。

  Code Show:

物件導向基本原則
        public class YellowRace
        {
            private string _color;

            public YellowRace()
            {
                _color = "Yellow";
            }

            public virtual string GetColor()
            {
                return _color;
            }
        }

        public class WhiteRace : YellowRace
        {
            private string _color;
            public WhiteRace()
            {
                _color = "White";
            }

            public override string GetColor()
            {
                return _color;
            }
        }

        static void Main(string[] args)
        {
            YellowRace yellowRace = new YellowRace();
            WhiteRace whiteRace = new WhiteRace();

            Console.WriteLine($"Yellow Race Skin Color Is: {yellowRace.GetColor()}");
            // 此處使用子類替換父類,會產生負作用 ,
        }
View Code

  上面程式碼違反 LIP 原則,負面影響:即黃種人,皮膚顏色應是黃色。

  可以重構,建立一個 Mankind 類, 白種人、黃種人都繼承它。

物件導向基本原則
        public abstract class Mankind
        {
            protected string _color;
            public abstract string GetColor();
        }

        public class YellowRace: Mankind
        {
            public YellowRace()
            {
                _color = "Yellow";
            }

            public override string GetColor()
            {
                return _color;
            }
        }

        public class WhiteRace : Mankind
        {
            public WhiteRace()
            {
                _color = "White";
            }

            public override string GetColor()
            {
                return _color;
            }
        }
View Code

 

  4、Interface Segregation Principle

  介面隔離原則描述:多個客戶端特定的介面,好過一個超級通用介面,即客戶端不應該實現使用不到的介面,或客戶端不應該依賴於不使用的方法。

  實踐中曾經閱讀過這樣的程式碼違反ISP 。 一個介面中有好多好多行為,其中一個行為在實現類中只有一個類真正用到了,其餘的方法體中都是 “throw new NotImplementedException();” ,此時應該著手重構它。

  

  題外,使用抽象類還是介面 ? 介面通常作為行為規範,表示能幹什麼 Can Do;而抽象類表示是什麼 Is A 。例如:印表機能列印,則印表機應該實現一個列印介面,同時印表機是一個電器則可以繼承電器基類。

 

  5、Dependency Inversion Principle

  依賴倒置原則描述:應該依賴抽象,而不是具體實現。

  現實中最長用的 ORM 框架,設計的時候遵循此原則,依賴抽象契約而不是某種特定資料庫的實現。

  回到僱傭王阿姨打掃房間的例子,依賴中介公司,就是依賴抽象,所有就可以讓任何阿姨打掃房間。

 

  6、DRY

  不要重複你自己原則描述:相同的程式碼不應該存在兩份以上。

  實踐中相同的程式碼同時存在多份,此時著手重構它。

 

三、總結

  以上介紹了幾種程式設計原則,遵循這些原則,就可以寫出 “Good Code”。

  適用於目前所有的面嚮物件語言,這些原則指導軟體開發,並積累了一些實踐。有助於軟體程式碼清晰可讀、可擴充套件、高內聚低耦合,有助於程式碼重構,清除程式碼異味。SOLID 被典型應用在,測試驅動開發、敏捷開發、自適應軟體開發等領域。

 

相關文章