接口分離原則


概述

當我們設計程序的時候,我們應當關心如何設計一個包含了若干子模塊的父類。    假如現在我們有一個模塊繼承自一個父類,而這個父類是一個接口。單單對這個模塊來說,一切夠用。但是如果我們添加其他的模塊,也繼承自這個接口,那么我們將不得不實現接口中的所有的方法,這種接口就被稱作富余接口,這種設計是不被贊賞的。

所以這也是接口分離原則產生的原因。所謂的接口分離原則就是指子模塊不必繼承並實現父模塊中不需要的東西。所以,對於富余接口來說,多創建一些分類明確,職責單一的小接口是正確的做法。

描述

下面的一個例子就違反了接口分離原則。讓我們來具體看看。

我們有一個Manager類(主管),它主要負責管理SuperWorker類和Worker類的(好的員工,一般的員工),這兩種Worker都是需要工作和吃飯的。但是突然有一天,Robert也來搶他們的飯碗了,Robert會工作,但是不需要吃飯的。所以,當我們定義了一個IWorker的接口的時候,SuperWorker和worker都能夠繼承是因為他們都需要吃喝,但是Robert繼承的時候就有點問題了,因為它只需要工作,不需要吃喝。

這里,IWorker接口就成了一個比較富余的接口。

如果我們保持當前設計不變,那么Robert就必須實現吃的動作,但是實際上,在吃的動作里面,我們是不能進行任何操作的。帶來的負面效果就是,Manager統計吃飯的時候,不需要吃飯的Robert也會被歸納其中。

using System;

namespace InterfaceSegregateDaemon
{
    interface IWorker
    {
        void Work();
        void Eat();
    }

    class Original:IWorker
    {
        public void Work()
        {
            Console.WriteLine("Worker is working");
        }

        public void Eat()
        {
            Console.WriteLine("Worker is eating");
        }
    }

    class SuperWorker : IWorker
    {
        public void Work()
        {
            Console.WriteLine("SuperWorker is working");
        }

        public void Eat()
        {
            Console.WriteLine("SuperWorker is eating");
        }
    }

    class Robert : IWorker
    {
        public void Work()
        {
            Console.WriteLine("Robert is working");
        }

        public void Eat()
        {
           //No Implementation
        }
    }

    class Manager
    {
        private IWorker worker;
        public Manager(IWorker worker)
        {
            this.worker = worker;
        }

        public void Manage()
        {
            worker.Work();
        }
    }
}
View Code

重構

下面的代碼是遵循了接口分離原則而設計的,通過將IWorker接口分離成兩個不同的接口,我們能夠將Robert類放棄吃的動作。當然,通過這種方式,我們可以為Robert類引入其他的操作,比如充電,比如休眠等等,那么我們只管創建一個IRecharge接口或者是ISleepy接口即可。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InterfaceSegregateDaemon
{
    interface IWorkable
    {
        void Work();
    }

    interface IEatable
    {
        void Eat();
    }

    interface IRechargable
    {
        void Recharge();
    }

    class Worker : IWorkable, IEatable
    {
        public void Work()
        {
            Console.WriteLine("Worker is working");
        }

        public void Eat()
        {
            Console.WriteLine("Worker is eating");
        }
    }

    class SuperWorker : IWorkable, IEatable
    {
        public void Work()
        {
            Console.WriteLine("SuperWorker is working");
        }

        public void Eat()
        {
            Console.WriteLine("SuperWorker is eating");
        }
    }

    class Robert : IWorkable,IRechargable
    {
        public void Work()
        {
            Console.WriteLine("Robert is working");
        }

        public void Recharge()
        {
            Console.WriteLine("Robert is recharging");
        }
    }

    class Manager
    {
        private IWorker worker;
        public Manager(IWorker worker)
        {
            this.worker = worker;
        }

        public void Manage()
        {
            worker.Work();
        }
    }
}
View Code

結論

如果當前的項目中有過多的富余接口,那么我們可以利用適配器模式進行分離。

如同接口分離原則一樣,其他的一些原則也許可能會要求我們有多余的時間和經歷去重構,同時這些原則的引入也會加大代碼的復雜度,但是,這些原則卻讓整個設計更加的靈活。如果在設計過程中,我們的需求發生變更,任何的修改,添加將會變得非常容易,代碼量將比預想的小很多。所以,如果你有足夠的經驗和能力,還是建議引入這些原則,畢竟,它會讓后續的代碼設計變得簡單且充滿樂趣。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM