SOLID的ISP

ISP(接口隔离原则)

定义:

  • 客户端不应该依赖它不需要的接口
  • 类间的依赖关系应该建立在最小的接口上

 

举例说明(为了保持突出主题,实例代码并不完善,且没有考虑异常),

 

  某天之前,小王设计I接口,用于业务处理, 有部分用户需要计费,有部分不需要,但均使用I接口。

  class I {

  public:

    virtual ~I(); 

    virtual bool charge() = 0;

    virtual void proc() = 0;

  };

 

  class A:public I

  {

  public:

    A(string const &account);

    virtual bool charge(); // if charged successfully, then return true;

    virtual void proc();

 

  private:

    string _account;

  };

 

  class B:public I

  {

  public:

    B(string const &account);

    virtual bool charge(); // directly return true;

    virtual void proc();

 

  private:

    string _account;

  };

 

  class Service

  {

  public:

    void do(string const &account)

    {

      I *p = NULL;

      // 130 用户要收费

      if ( 0 == account.compare(0,3,"130") )

      {

        p = new A(account);

      }

      // 非130用户免费

      else

      {

        p = new B(account);

      }

 

      if (!p->charge())

      {

        return;

      }

 

      p->proc();

    }

 

  };

 

  后来用户提出需求,需要对扣费了的用户,生成话单记录。

  对于A类用户,在charge()方法中,记录话单即可。

  而对于B类用户,不需做任何调整。

  从这一例来看,ISP并没有发挥多大的作用。

 

  因此,ISP并不是任何时刻都必须使用。要深入分析,找到他到底解决什么样的根本问题,才是最重要的。

 

 

  本例中,由于Service类中业务逻辑非常简单,因此未看出有何不妥。

      但如果客户变更需求,对于A类用户需要在计费结束的时候,通知用户扣费的结果。那么我们把Service::do稍作修改,

 

  void Service::do(string const &account)

  {

      I *p = NULL;

      

      ...

 

      

      if (!p->charge())

      {

        //发送通知消息,表明扣费失败

        return -1;

      }

      else

      {

        //发送通知消息,表明扣费成功

      }

 

      p->proc();

  }

 

  这样,对于B类用户来说,charge()接口无论改为返回true还是false都不能避免消息下发,这样,在没有扣费的情况下仍然下发了消息。

虽然,可以通过:

1.在Service::do里面特殊处理,2.在B::charge()中修改类似全局变量的方式来通知Service::do在后面特殊处理,或者修改接口

来避免业务逻辑错误。但本身带来了诸多出错的机会。

 

  因此,从本例来看,问题出现在A类用户是要计费的,B类是不计费的。而接口公用charge(),也就是计费接口。

因此,服务是依赖计费这个接口来进行实现的。所以,上下文会根据计费成功或者计费失败来设计上下文,对于根本

没有计费的情况,就难以覆盖了。除非,对于计费的结果不需要有任何业务逻辑来处理,那么就没有多大的影响。

所以,如果不是业务专家,对于需求还在澄清阶段,请严格遵循ISP。

 

 

 

 

 

 

posted @ 2013-06-11 23:17  Lawrence.Lau  阅读(190)  评论(0)    收藏  举报