接口隔离原则只是单一职责原则的替代品吗?
我认为,如果我的班级满足 SRP,则无需提取多个接口。
所以 ISP 看起来像是解决方案,以防我们出于某种原因不得不破坏 SRP。
我对吗 ?
接口隔离原则只是单一职责原则的替代品吗?
我认为,如果我的班级满足 SRP,则无需提取多个接口。
所以 ISP 看起来像是解决方案,以防我们出于某种原因不得不破坏 SRP。
我对吗 ?
不。以一个负责将数据持久保存在例如硬盘上的类为例。将课程分成读和写部分没有实际意义。但是有些客户端应该只使用该类来读取数据,有些客户端只用于写入数据,有些则两者兼而有之。在这里应用具有三个不同接口的 ISP 将是一个不错的解决方案。
我认为,如果我的班级满足 SRP,则无需提取多个接口。
单一职责原则是一个类(或一个方法)不应该有多个改变的理由(即每个只负责一个特性)。为了兑现这一点,您会发现自己随着系统的发展而创建了新的类。
例如,如果你从一个Car
类开始并发现你需要改变齿轮的功能,你将把它提取到一个Gearbox
类中。这意味着如果您更改齿轮更改背后的机制,则父Car
类不需要更改。如果您为您的汽车添加动力转向,您将再次将其提取到它自己的类中。收音机将是另一门课。
这种抽象的级联将在您的整个Car
班级中发生。当您从Car
自身向下移动时,您会发现每个类的细节都在增加——例如,虽然Car
该类可能有一个changeGear()
方法允许用户选择要使用的齿轮,但Gearbox
该类将关注制作的细节发生这种情况(例如踩下离合器、分离当前档位、选择新档位等)
然而,对于 OO 设计,我们不希望将我们的细节暴露Gearbox
给最终用户——我们希望他们与我们的系统进行高度抽象的交互,而不需要知道内部是如何工作的。我们还希望隔离这些内部结构,以便我们可以在将来更改它们而无需用户重构他们的代码(这就是我们将它们标记为private
or的原因protected
)。
Car
正因为如此,我们让用户只能通过类本身与我们的汽车进行交互。这就是接口隔离原则的用武之地。SRP 确保Car
类将其子组件委托给不同的类,但我们所有的public
方法仍将通过Car
类本身调用。ISP确保我们不是将所有这些集中在一个接口中,而是创建逻辑区别并为相关功能公开多个接口。
不。
一个类可以实现多个接口,但它应该实现只适用于它的方法。
假设您有 10 多种不同的功能,例如Climb, Think, Learn, Apply
. 类Dog
可以有 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
同一个例子中类的实现。