接口分离原则

概述

当我们设计程序的时候,我们应当关心如何设计一个包含了若干子模块的父类。    假如现在我们有一个模块继承自一个父类,而这个父类是一个接口。单单对这个模块来说,一切够用。但是如果我们添加其他的模块,也继承自这个接口,那么我们将不得不实现接口中的所有的方法,这种接口就被称作富余接口,这种设计是不被赞赏的。

所以这也是接口分离原则产生的原因。所谓的接口分离原则就是指子模块不必继承并实现父模块中不需要的东西。所以,对于富余接口来说,多创建一些分类明确,职责单一的小接口是正确的做法。

描述

下面的一个例子就违反了接口分离原则。让我们来具体看看。

我们有一个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

结论

如果当前的项目中有过多的富余接口,那么我们可以利用适配器模式进行分离。

如同接口分离原则一样,其他的一些原则也许可能会要求我们有多余的时间和经历去重构,同时这些原则的引入也会加大代码的复杂度,但是,这些原则却让整个设计更加的灵活。如果在设计过程中,我们的需求发生变更,任何的修改,添加将会变得非常容易,代码量将比预想的小很多。所以,如果你有足够的经验和能力,还是建议引入这些原则,毕竟,它会让后续的代码设计变得简单且充满乐趣。

原文地址:https://www.cnblogs.com/scy251147/p/3268908.html