大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C#技巧 > 设计模式六大原则(4)--接口隔离原则

设计模式六大原则(4)--接口隔离原则

关键词:设计模式接口隔离原则  阅读(646) 赞(12)

[摘要]本文是对设计模式六大原则之接口隔离原则的讲解,对学习C#编程技术有所帮助,与大家分享。

定义:

客户端不应该依赖它不需要的接口;类之间的依赖关系应建立在最小的接口之上。接口隔离原则英文全称为Interface Segregation Principle ,简称为ISP。

个人理解:

通俗的来说,接口不能臃肿庞大,而使根据具体需要尽量的细化。接口中的方法也要尽可能的少。接口是设计对外的一种契约,通过分散定义多个接口可以预防将来变更的扩散,使得真个系统变得更加稳定和更具有可维护性。

问题由来:

类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类C不是最小的接口,那么类C和类D中肯定存在对应接口I中不需要的方法。如下图所示:

此时详细代码如下所示:

/// <summary>
    /// 接口I,定义了5个方法
    /// </summary>
    public interface I
    {
        void Method1();
        void Method2();
        void Method3();
        void Method4();
        void Method5();
    }
    /// <summary>
    /// 类A
    /// </summary>
    public class A
    {
        public void Depend1(I i)
        {
            i.Method1();
        }
        public void Depend2(I i)
        {
            i.Method2();
        }
        public void Depend3(I i)
        {
            i.Method3();
        }
    }

    public class B : I
    {
        public void Method1()
        {
            Console.WriteLine("类B实现接口I的方法1");
        }
        public void Method2()
        {
            Console.WriteLine("类B实现接口I的方法2");
        }
        public void Method3()
        {
            Console.WriteLine("类B实现接口I的方法3");
        }
        //对于类B来说,Method4和Method5方法不是必需的。但是既然继承了接口I,
        //即使方法体为空,也要实现这两个方法
        public void Method4()
        {
            
        }
        public void Method5()
        {
            
        }
    }
    /// <summary>
    /// 类C
    /// </summary>
    public class C 
    {
        public void Depend1(I i)
        {
            i.Method1();
        }
        public void Depend2(I i)
        {
            i.Method4();
        }
        public void Depend3(I i)
        {
            i.Method5();
        }
    }

    public class D : I
    {
        public void Method1()
        {
            Console.WriteLine("类D实现接口I的方法1");
        }
        //对于类B来说,Method4和Method5方法不是必需的。但是既然继承了接口I,
        //即使方法体为空,也要实现这两个方法
        public void Method2()
        { 
        }
        public void Method3()
        {
        }
        
        public void Method4()
        {
            Console.WriteLine("类D实现接口I的方法4");
        }
        public void Method5()
        {
            Console.WriteLine("类D实现接口I的方法5");
        }
    }

解决方案:

将臃肿的接口I细分为若干个接口,类A和类C分别与它们对应的接口建立依赖关系。接口隔离原则的核心定义是接口尽量小,不出现臃肿的接口(Fat Interface),但是“小”是有限度的,首先就是不能违反单一职责原则。如果一个接口设计过于臃肿,那么继承此接口的实例不管需不需要接口的所有方法都必须要实现该接口的所有方法。所以对于上面的解决是将接口I细分为3个接口,然后类A和C分别对应实现,类图结构如下所示:

细化接口后的详细代码如下所示:

/// <summary>
    /// 接口I1,定义了方法1
    /// </summary>
    public interface I1
    {
        void Method1();
    }
    /// <summary>
    /// 接口I2,定义了方法2和3
    /// </summary>
    public interface I2
    {
        void Method2();
        void Method3();
    }
    /// <summary>
    /// 接口I3,定义了方法4和5
    /// </summary>
    public interface I3
    {
        void Method4();
        void Method5();
    }
    /// <summary>
    /// 类A
    /// </summary>
    public class A
    {
        public void Depend1(I1 i)
        {
            i.Method1();
        }
        public void Depend2(I2 i)
        {
            i.Method2();
        }
        public void Depend3(I2 i)
        {
            i.Method3();
        }
    }

    public class B : I1,I2
    {
        public void Method1()
        {
            Console.WriteLine("类B实现接口I的方法1");
        }
        public void Method2()
        {
            Console.WriteLine("类B实现接口I的方法2");
        }
        public void Method3()
        {
            Console.WriteLine("类B实现接口I的方法3");
        }
        
    }
    /// <summary>
    /// 类C
    /// </summary>
    public class C 
    {
        public void Depend1(I1 i)
        {
            i.Method1();
        }
        public void Depend2(I3 i)
        {
            i.Method4();
        }
        public void Depend3(I3 i)
        {
            i.Method5();
        }
    }

    public class D : I1,I3
    {
        public void Method1()
        {
            Console.WriteLine("类D实现接口I的方法1");
        }
        public void Method4()
        {
            Console.WriteLine("类D实现接口I的方法4");
        }
        public void Method5()
        {
            Console.WriteLine("类D实现接口I的方法5");
        }
    }

代码结构如下:

image

看到该图你就会很明白了吧!

接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。本文例子中,将一个庞大的接口变更为3个专用的接口所采用的就是接口隔离原则。在程序设计中,依赖几个专用的接口要比依赖一个综合的接口更灵活。接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

顺便说一下单一职责原则和接口隔离原则的区别。单一职责原则针对的是类,其次才是接口和方法,它关注的关键点是“职责”,对应的是具体的实现部分要“单一”;而接口隔离原则针对的是抽象级别,它关注的是抽象与具体实现的隔离,对应的是抽象接口之间的隔离。

在实际使用接口隔离原则中我们应注意以下3点:

1.接口应尽量小,方法尽量少,这符合接口隔离原则定义,但是在具体项目中要适度,不可能创建非常多的接口,所以应用接口隔离原则也要具体问题具体分析。

2.定制服务,定制服务就是单独为一个个体提供优良服务。

3.提高内聚(高内聚就是要提高接口、类、模块的处理能力,减少对外的交互),减少对外交互,使用最少的方法完成尽可能多的事情。



相关评论