只是向 Stack Overflow 和 Microsoft 开发社区提出关于 OO 软件设计原则(称为 SOLID)的想法和问题。请问里氏替换原则和依赖倒置原则有什么区别?我已经考虑了一段时间,但我不确定有什么区别。请问你能告诉我吗?非常欢迎任何想法/反馈。
3 回答
Liskov 的替代原则陈述如下:
一个类应该可以直接替换为它的基类
这意味着如果一个子类扩展了一个父类,它应该是直接可替换的。 可在此处查看图片
如果你看以鸟为例。不是所有的鸟都会飞——但有些鸟会飞。
让我们看一个java示例:
Bird ostrich = new Ostrich();
如果我要将我的鸵鸟视为鸟(是基类/父类),并且我们在Bird中具有让鸵鸟飞翔的功能,即使它们不应该!
所以我们可以分离出结构: Liskov's Refactored hierarchy
当被认为是一个单独的原则时,依赖倒置更容易。
如果我们有一个类调用一个类。这使得以后更改它变得非常困难,并且需要我们更改源代码。再次让我们看一个代码示例。
public class App {
public static void main(String[] args) {
Greeting greeting = new Greeting();
greeting.sayHello(new Friend());
greeting.sayHello(new Enemy());
}
}
public class Greeting {
public void sayHello(Person person) {
person.greet();
}
}
public interface Person {
public void greet();
}
public class Friend implements Person {
public void greet() {
System.out.println("Hello my friend");
}
}
public class Enemy implements Person {
public void greet() {
System.out.println("Go away");
}
}
这里我们传递了两个项目(朋友和敌人)的父对象(人)。如果我们通过一个 Friend 对象,我们将需要一个单独的相同方法用于 Enemy 方法。我们可以使用 Open/Closed 原则来拥有一个可以调用 Friend 或 Enemy 或将来可能扩展 Person 的任何方法的方法。依赖倒置是传递父对象而不是 sayHello() 方法创建一个类。这意味着我们调用哪个Parent对象取决于App,而不是sayHello()决定调用哪个对象。
使用依赖倒置是更好的做法。类 greet() 调用不是一成不变的,只要传递的类是实现 Person 的类。
这意味着不是 App 依赖于 Friend。Friend 或 Enemy 是否被调用取决于 App。
像这样传递责任意味着我们的代码可以很容易地维护和更改。使用上下文和依赖注入,配置文件可以确定在引用指定接口时要使用哪种类型的对象。
替换原则意味着您使用抽象。抽象是好的,因为它们使您的代码更加通用、可重用和有价值。例如,如果您的代码与抽象Vehicle
而不是更具体的代码一起Car
使用,那么您也可以使用相同的代码而无需任何更改,也可以与其他车辆(例如Bicycle
,Truck
甚至)一起使用Ship
,并且它将继续正常工作而不会出现问题。当然,要使这种“替代”起作用,您必须确保所有Vehicle
s 遵循相同的约定,这通常意味着它们实现了一个公共接口或扩展了一个公共超类。
依赖注入使您的代码更好,因为它切断了类之间不必要的联系。这再次使这些类在不同的场景中可重用。例如,如果您的班级从文件中获取数据,那么下次您的数据将在数据库中时,您将遇到问题。你的班级会突然变成一个 if-then-else 案例的沼泽,试图处理不同的事情,这将是一场噩梦。依赖注入将你的类从这个责任中解放出来——即你的类只是“需要数据”,而调用者有责任确保数据已连接(也称为“注入”)到其中。从技术上讲,依赖注入只是简单地设置一个变量,例如myObject.dataSource = databaseDataSource
、 或myObject.dataSource = fileDataSource
。