【问题标题】:Is Interface segregation principle only a substitue for Single responsibility principle?接口隔离原则是否只是单一责任原则的替代品?
【发布时间】:2011-11-11 19:35:45
【问题描述】:

接口隔离原则只是单一职责原则的替代品吗?

我认为如果我的类满足 SRP,就不需要提取多个接口。

所以 ISP 看起来像是解决方案,以防我们出于某种原因不得不中断 SRP。

我说的对吗?

【问题讨论】:

    标签: design-patterns solid-principles single-responsibility-principle interface-segregation-principle


    【解决方案1】:

    没有。以一个类的例子为例,其职责是持久化数据,例如硬盘。将课程分成读和写部分没有实际意义。但是有些客户端应该只使用类来读取数据,有些客户端只写数据,有些则两者兼而有之。在这里应用具有三个不同接口的 ISP 将是一个不错的解决方案。

    【讨论】:

    【解决方案2】:

    我认为,如果我的班级满足 SRP,则无需提取更多 不止一个接口。

    单一职责原则是一个类(或一个方法)不应该有多个改变的理由(即每个人只负责一个特性)。为了兑现这一点,您会发现自己随着系统的发展而创建了新的类。

    例如如果您从Car 类开始并发现您需要更改齿轮的功能,您将把它提取到Gearbox 类中。这意味着如果您更改齿轮更改背后的机制,则父类Car 不需要更改。如果您为您的汽车添加动力转向,您将再次将其提取到它自己的类中。收音机将是另一类。

    这种抽象级联将在您的 Car 类中发生。当您从Car 本身向下移动时,您会发现每个类的细节都在增加——例如虽然Car 类可能有一个changeGear() 方法允许用户选择要接合的档位,但Gearbox 类将负责实现这一点(例如踩下离合器、分离当前档位) ,选择新齿轮等)

    然而,对于 OO 设计,我们不希望将 Gearbox 的细节暴露给最终用户——我们希望他们与我们的系统进行高级抽象交互,而不需要知道内部如何工作。我们还想隔离这些内部结构,以便我们将来可以更改它们而无需用户重构他们的代码(这就是为什么我们将它们标记为privateprotected)。

    因此,我们只允许用户通过Car 类本身与我们的汽车进行交互。 接口隔离原则的用武之地。SRP 确保Car 类将其子组件委托给不同的类,但我们所有的public 方法将仍然通过Car 类本身调用。 ISP 确保我们不是将所有这些集中在一个界面中,而是创建逻辑区别并为相关功能公开多个界面。

    【讨论】:

      【解决方案3】:

      没有。

      一个类可以实现多个接口,但它应该实现只适用于它的方法。

      假设您有 10 多种不同的功能,例如 Climb, Think, Learn, ApplyDog 类可以有 2 个功能,Cat 类可以有 2 个功能,Man 类可以有 6 个功能。在各个类中仅实现适用的功能是有意义的。

      看看这段代码。

      public class ISRDemo{
          public static void main(String args[]){
      
              Dog dog = new Dog("Jack",16);
              System.out.println(dog);
      
              Learn dl = dog;
              dl.learn();
              ProtectOwner p = dog;
              p.protectOwner();
      
              Cat cat = new Cat("Joe",20);
              System.out.println(cat);
              Climb c = cat;
              c.climb();
              Remember r = cat;
              cat.doRemember();       
      
              Man man = new Man("Ravindra",40);   
              System.out.println(man);
              Think t = man;
              t.think();
              Learn l = man;
              l.learn();
              Apply a = man;
              a.apply();
              PlaySports pm = man;
              pm.playSports();
              Remember rm = man;
              rm.doRemember();
      
          }
      }
      
      class Dog implements Learn,ProtectOwner{
          private String name;
          private int age;
          public Dog(String name,int age){
              this.name = name;
              this.age = age;
          }
      
          public void learn(){
              System.out.println(this.getClass().getSimpleName()+ " can learn");
          }
          public void protectOwner(){
              System.out.println(this.getClass().getSimpleName()+ " can protect owner");
          }
          public String toString(){
              return "Dog :"+name+":Age:"+age;
          }
      }
      class Cat implements Climb,Remember {
          private String name;
          private int age;
          public Cat(String name,int age){
              this.name = name;
              this.age = age;
          }
          public void climb(){
              System.out.println(this.getClass().getSimpleName()+ " can climb");
          }
          public void doRemember(){
              System.out.println(this.getClass().getSimpleName()+ " can remember");
          }
          public String toString(){
              return "Cat :"+name+":Age:"+age;
          }
      }
      interface ProtectOwner {
          public void protectOwner();
      }
      interface Remember{
          public void doRemember();
      }
      interface Climb{
          public void climb();
      }
      interface Think {
          public void think();
      }
      interface Learn {
          public void learn();
      }
      interface Apply{
          public void apply();
      }
      interface PlaySports{
          public void playSports();
      }
      
      class Man implements Think,Learn,Apply,PlaySports,Remember{
          String name;
          int age;
      
          public Man(String name,int age){
              this.name = name;
              this.age = age;
          }
          public void think(){
              System.out.println(this.getClass().getSimpleName() + " can think");
          }
          public void learn(){
              System.out.println(this.getClass().getSimpleName() + " can learn");
          }
          public void apply(){
              System.out.println(this.getClass().getSimpleName() + " can apply");
          }
          public void playSports(){
              System.out.println(this.getClass().getSimpleName() + " can play sports");
          }
          public void doRemember(){
              System.out.println(this.getClass().getSimpleName() + " can remember");
          }
          public String toString(){
              return "Man :"+name+":Age:"+age;
          }
      }
      

      输出:

      java ISRDemo
      Dog :Jack:Age:16
      Dog can learn
      Dog can protect owner
      Cat :Joe:Age:20
      Cat can climb
      Cat can remember
      Man :Ravindra:Age:40
      Man can think
      Man can learn
      Man can apply
      Man can play sports
      Man can remember
      

      在上面的示例中,接口隔离建议在 10 个接口中定义 10 个功能,而不是在胖接口中声明所有这些功能。但这并不意味着您需要不同的类来满足单一职责标准

      查看同一示例中 Dog, Cat and Man 类的实现。

      【讨论】:

        猜你喜欢
        • 2022-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多