程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 設計模式六大原則(5)—迪米特法則,設計模式六大

設計模式六大原則(5)—迪米特法則,設計模式六大

編輯:C#入門知識

設計模式六大原則(5)—迪米特法則,設計模式六大


定義:

一個對象應該對其它的對象保持最少的了解。迪米特法則又稱為最少知識法則,英文全稱為Least Knowledge Principle ,簡稱為LKP。

個人理解:

迪米特法則主要目的是類間解耦,弱耦合。只有類弱耦合了後,類的復用性才會提高。

問題由來:

類之間的關系越密切,類之間的耦合程度越高。當一個類發改變時,耦合度越大,對另一類的影響也就越大。

解決方案:

盡量降低類之間的耦合度。

從事編程的都知道,軟件編程總的原則是低耦合、高內聚,只有這樣才能提高代碼的復用率,而這正是迪米特法則所要求的。迪米特法則還有一個更簡單的定義:只與直接的朋友通信。首先來解釋一下什麼是直接的朋友:每個對象都會與其他對象有耦合關系,只要兩個對象之間有耦合關系,我們就說這兩個對象之間是朋友關系。耦合的方式很多,依賴、關聯、組合、聚合等。其中,我們稱出現成員變量、方法參數、方法返回值中的類為直接的朋友,而出現在局部變量中的類則不是直接的朋友。也就是說,陌生的類最好不要作為局部變量的形式出現在類的內部。

舉例說明:

老師(Teacher類)對組長(GroupLeader類)發布命令,組長對女生(Gril類)人數統計並輸出來。違反迪米特法則的代碼如下所示:

public class Girl
    {
        
    }

    public class GroubLeader
    {
        //有清查女生的工作
        public void CountGrilNumber(List<Girl> girlslist)
        {
            Console.WriteLine("女生的數量是"+girlslist.Count);
        }
    }

    public class Teacher
    {
        public void Command(GroubLeader groubLeader)
        {
            var grilList = new List<Girl>();
            //初始化女生列表
            for (var i = 0; i < 30; i++)
            {
                grilList.Add(new Girl());
            }
            //告訴體育委員要清查女生數量
            groubLeader.CountGrilNumber(grilList);
        }
    }
    class Client
    {
        static void Main(string[] args)
        {
            var teacher = new Teacher();
            //老師發布命令
            teacher.Command(new GroubLeader());
            Console.ReadKey();
        } 
    }

上面的代碼中Teacher初始化了Gril的List列表,老師直接操作女生的列表這顯然不符合常規,更不符合迪米特法則,正常的順序是老師對組長發布命令,組長統計女生人數。類的關系要盡量的解耦,降低他們的耦合度。改進方法是GroupLeader內部私有化一個List<Gril>變量,在構造GroupLeader變量時傳遞List<Gril>參數,這樣就降低了Gril和GroupLeader的耦合度。改進代碼如下所示:

public class Girl
    {
        
    }

    public class GroubLeader
    {
        private readonly List<Girl> _girList;

        public GroubLeader(List<Girl> girlList)
        {
            _girList = girlList;
        }
        //有清查女生的工作
        public void CountGrilNumber()
        {
            Console.WriteLine("女生的數量是" + _girList.Count);
        }
    }

    public class Teacher
    {
        public void Command(GroubLeader groubLeader)
        {
            
            //告訴體育委員要清查女生數量
            groubLeader.CountGrilNumber();
        }
    }
    class Client
    {
        static void Main(string[] args)
        {
            var girlList = new List<Girl>();
            //初始化女生列表
            for (var i = 0; i < 30; i++)
            {
                girlList.Add(new Girl());
            }
            var teacher = new Teacher();
            //老師發布命令
            teacher.Command(new GroubLeader(girlList));
            Console.ReadKey();
        } 
    }

上面的例子只是單純的說明迪米特法則的使用,可能有些牽強,關鍵還是理解一個對象應盡量對其它對象保持少的了解這句話的意思。


JAVA面向對象六大原則是什?

1) Open-Close Principle(OCP),開-閉原則,講的是設計要對擴展有好的支持,而對修改要嚴格限制。這是最重要也是最為抽象的原則,基本上我們所說的Reusable Software既是基於此原則而開發的。其他的原則也是對它的實現提供了路徑。

2) Liskov Substituition Principle(LSP),裡氏代換原則,很嚴格的原則,規則是“子類必須能夠替換基類,否則不應當設計為其子類。”也就是說,子類只能去擴展基類,而不是隱藏或覆蓋基類.
3) Dependence Inversion Principle(DIP),依賴倒換原則,“設計要依賴於抽象而不是具體化”。換句話說就是設計的時候我們要用抽象來思考,而不是一上來就開始劃分我需要哪些哪些類,因為這些是具體。這樣做有什麼好處呢?人的思維本身實際上就是很抽象的,我們分析問題的時候不是一下子就考慮到細節,而是很抽象的將整個問題都構思出來,所以面向抽象設計是符合人的思維的。另外這個原則會很好的支持OCP,面向抽象的設計使我們能夠不必太多依賴於實現,這樣擴展就成為了可能,這個原則也是另一篇文章《Design by Contract》的基石。

4) Interface Segregation Principle(ISP),“將大的接口打散成多個小接口”,這樣做的好處很明顯,我不知道有沒有必要再繼續描述了,為了節省篇幅,實際上我對這些原則只是做了一個小總結,如果有需要更深入了解的話推薦看《Java與模式》,MS MVP的一本巨作!^_^

5) Composition/Aggregation Reuse Principle(CARP),設計者首先應當考慮復合/聚合,而不是繼承(因為它很直觀,第一印象就是“哦,這個就是OO啊”)。這個就是所謂的“Favor Composition over Inheritance”,在實踐中復合/聚合會帶來比繼承更大的利益,所以要優先考慮。

6) Law of Demeter or Least Knowlegde Principle(LoD or LKP),迪米特法則或最少知識原則,這個原則首次在Demeter系統中得到正式運用,所以定義為迪米特法則。它講的是“一個對象應當盡可能少的去了解其他對象”。也就是又一個關於如何松耦合(Loosely-Coupled)的法則。
 

AS3簡述一下向上轉換與向下轉換的概念

去百度查一下 裡氏代換原則,這是設計模式的基礎6大設計原則之一

單一職責、裡氏替換(代換)、依賴倒置、接口隔離、迪米特法則、開閉原則

或者直白地說,就是你要搞懂as3.0的 一個統一,兩大分支,事件驅動

一個統一是所有顯示對象歸屬繼承自 flash.display.DisplayObject類
其下分兩大分支
第一分支 flash.display.InteractiveObject (可交互對象) 和 不可交互對象
第二分支 flash.display.DisplayObjectContainer(容器對象) 和 非容器對象

而使用到 向上轉換和向下轉換的情況 在使用事件時很常見

如平時我們

mc.addEventListener(MouseEvent.CLICK, onClick_func);

function onClick_func(_evt:MouseEvent):void{
var _mc:MovieClip = _evt.target as MovieClip;
//這個事件處理函數中 _evt.target as MovieClip; 就使用了向下轉換,把事件傳遞中的
// flash.display.DisplayObject 類型 轉換成其子類 flash.display.MovieClip
}

向上轉換

比如

function setX(_obj:DisplayObject):void{
_obj.x = 100;
}

這個函數的參數使用了 父類 DisplayObject作為類型,那麼表明調用這個函數傳入的參數可以是所有DisplayObject的子類 比如 MovieClip ,比如 SimpleButton ,比如 TextField(文本框) 等等

子類 父類都是基於接口的向上轉換或向下轉換來應用的


 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved