类间的依赖关系应该建立在最小的接口上(不应该依赖他不需要的接口)
客户端不应该依赖它不需要的接口
在理解这两句话之前,先看一下什么是接口,什么是隔离
接口:一种约束形式,为不相关的类提供约定好的处理方法;在C++中,包含纯虚函数的类叫做接口类;
隔离:不让聚在一起,使断绝往来
因此接口隔离第一句话大致是指:一个类不需要某个接口中的全部方法,就不要依赖这个接口,而去依赖能满足该类并方法最少的接口;第二句话中的客户端指的是需求方,在下面例子中,IBehavior 类是接口类,fish和bird类继承自该类并使用该类提供的接口(客户端依赖接口),但是在第一份代码中,客户端如鱼类依赖了它不需要的接口(fly方法),因此违背接口隔离原则中的“客户端不应该依赖它不需要的接口”。
例子1:
#include
class IBehavior {
public:
virtual void fly() = 0;
virtual void swim() = 0;
};
class Fish : public IBehavior {
virtual void fly() {
std::cout <<"我是鱼不会飞行 !"<<std::endl;
}
virtual void swim() {
std::cout <<"我是鱼游泳真快乐!"<<std::endl;
}
};
class Bird : public IBehavior {
virtual void fly() {
std::cout <<"我是鸟儿飞行真快乐!"<<std::endl;
}
virtual void swim() {
std::cout <<"我是鸟儿不会游泳!"<<std::endl;
}
};
class Zoo {
// Fish fish;
public:
void showSwim(IBehavior* behavior) {
behavior->swim();
}
void showFly(IBehavior* behavior) {
behavior->fly();
}
};
int main() {
Zoo z;
Fish* fish = new Fish();
Bird* bird = new Bird();
z.showSwim(fish);
z.showFly(bird);
return 1;
}
第3行定义了一个动物行为类,使用纯虚函数定义了游泳和飞行两种动作接口(且耦合在一个类中,在没有满足接口隔离原则下),鱼类和鸟类分别继承了动物行为类,根据纯虚函数的特点,鸟类和鱼类中必须重写fly和swim方法(否则编译不通过)。最后在Zoo类中,包含showFly和showSwim两种方法,根据IBehavior*类型的不同,指向不同的对象,实现不同的行为,但是该设计的弊端是:
臃肿(多余方法)接口设计,称之为胖接口,一点接口方法变动,会影响所有实现该接口的客户端类程序,比如当在行为类中增加新的动作接口时,如“爬行”,需要在所有派生动物类中重写爬行方法,耦合度过高。
示例2:
#include
class IFlyBehavior {
public:
virtual void fly() = 0;
};
class ISwimBehavior {
public:
virtual void swim() = 0;
};
class Fish : public ISwimBehavior {
virtual void swim() {
std::cout <<"我是鱼游泳真快乐!"<<std::endl;
}
};
class Bird : public IFlyBehavior {
virtual void fly() {
std::cout <<"我是鸟儿飞行真快乐!"<<std::endl;
}
};
class Yazi : public IFlyBehavior, public ISwimBehavior{
virtual void fly() {
std::cout <<"我是鸭子飞行真快乐!"<<std::endl;
}
virtual void swim() {
std::cout <<"我是鸭子游泳真快乐!"<<std::endl;
}
};
class Zoo {
public:
void showSwim(ISwimBehavior* behavior) {
behavior->swim();
}
void showFly(IFlyBehavior* behavior) {
behavior->fly();
}
};
int main() {
Zoo z;
Fish* fish = new Fish();
Bird* bird = new Bird();
Yazi* yazi = new Yazi();
z.showSwim(fish);
z.showFly(bird);
z.showSwim(yazi);
z.showFly(yazi);
return 1;
}
增加动物行为类的方法时,不影响现有鸟类、鱼类功能(不需要做任何变更)
增加动物类别时,比如鸭子类,只需要按照需要多重继承需要的接口即可,比如飞行行为类、游泳行为类。
把一个臃肿的接口拆分为两个独立的接口所依赖的原则就是接口隔离原则。接口隔离原则是对接口进行规范约束