SRP
,顾名思义,就是一个类只负责一个职责。它的定义也很简单:There should never be more than one reason for a class to change.
里氏替换原则的定义如下:
Functions that use use pointers or references to base classes must be able to use objects of derived classes without knowing it.
public class Fruit { void introduce() { System.out.println("我是水果父类..."); } }
其次,它有一个子类,苹果类:
public class Apple extends Fruit { @Override void introduce() { System.out.println("我是水果子类——苹果"); } }
客户端代码如下:
public static void main(String[] args) { Fruit fruit = new Fruit(); HashMap map = new HashMap<>(); fruit.introduce(); }
运行结果:
我是水果父类...
那么,如果按照 LSP
原则,所有父类出现的地方都能换成其子类,代码如下:
public static void main(String[] args) { Apple fruit = new Apple(); HashMap map = new HashMap<>(); fruit.introduce(); }
那么运行结果就会变成:
我是水果子类——苹果
High level modules should not depend upon low level modules.
Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.
public class Apple { public void eaten() { System.out.println("正在吃苹果..."); } }
然后写人的类:
public class Person { void eat(Apple apple) { apple.eaten(); } }
这样,在客户端中我们就可以这样调用:
Person xiaoMing = new Person(); Apple apple = new Apple(); xiaoMing.eat(apple);
但是这样就有一个问题,如果我不仅仅想吃苹果,还想吃橘子怎么办,在 Person
类中再加一个函数处理橘子?那么吃别的水果呢??总不能程序中每增加一种水果就要在其中增加一个函数吧。
这时候就需要接口了(抽象类也是可以的)
程序就可以这样更改,增加一个水果接口:
public interface Fruit { void eaten(); }
让苹果类实现该接口:
public class Apple implements Fruit { @Override public void eaten() { System.out.println("正在吃苹果..."); } }
然后将Person类中的函数的参数稍作修改:
public class Person { void eat(Fruit fruit) { fruit.eaten(); } }
这样,客户端代码也稍作修改:
Person xiaoMing = new Person(); Fruit apple = new Apple(); xiaoMing.eat(apple);
Software entities like classes, modules and functions should be open for extension but closed for modifications.
原文:https://www.cnblogs.com/1013wang/p/12269530.html