本文讲解设计模式七大原则中的里氏替换原则、开闭原则 我的上一篇博文 讲述了单一职责原则、接口隔离原则、依赖倒转原则
详情可以戳这里:七大原则上篇
现在进入本文的正题
里氏替换原则
里氏 里氏 顾名思义,里氏替换原则是1988年麻省理工以为姓里的女士提出来的
源于对继承的思考
- 父类中凡是已经实现好的方法,实际上是在设定规范和契约。虽然它并不强制要求所有子类必须遵守这些约定,但是如果子类对这些已经实现了的方法任意修改,则会对整个继承体系造成破坏。
- 继承在给程序设计带来便利的同时也带来了弊端。若一个类的功能被其他类继承,则当需要对这个类做修改时,必须考虑到所有子类。降低了程序的可移植性,增加了对象间的耦合。
- 而如何正确的使用继承呢
里氏原则提出
- 如果每个类型为T1的对象O1,都有对应类型为T2的对象O2 。使得已T1定义的程序P,将P中的所有对象O1替换为O2时,程序P并没有发生什么变化。那么类型T2是类型T1的子类型,换句话说:所有使用基类的地方必须能透明的使用其子类的对象
- 在继承时 子类尽量不要重写父类的方法
- 可以通过聚合、组合、依赖 来解决继承问题
开闭原则
基本介绍
- 一个软件实体如类、模块、函数,应当对扩展开放(提供方),对修改关闭(使用方)
- 当软件需要变化的时候,尽量扩展软件来实现变化,而不是修改现有代码
案例
设计背景: 编写一个绘画程序,通过输入图形的类型绘制对应的图片。并在客户端中调用
反面案例
声明图形基类
class Shape {
int m_type;
}
定义长方形
class Rectangle extends Shape {
Rectangle() {
super.m_type = 1;
}
}
定义圆形
class Circle extends Shape {
Circle() {
super.m_type = 2;
}
}
定义绘画工具类
class GraphicEditor {
public void drawShape(Shape shape) {
if (shape.m_type == 1) {
drawRectangle(shape);
} else if (shape.m_type == 2) {
drawCircle(shape);
}
}
public void drawRectangle(Shape shape) {
System.out.println("长方形");
}
public void drawCircle(Shape shape) {
System.out.println("圆形");
}
}
客户端调用
public class OpenClose1 {
public static void main(String[] args) {
GraphicEditor graphicEditor=new GraphicEditor();
graphicEditor.drawShape(new Rectangle());
graphicEditor.drawShape(new Circle());
}
}
这里假如我们需要增加三角形或者其他图形 则需要新增对应实体,以及修改工具类中的绘制方法。这样就违背了开闭原则,绘画工具类属于使用方,这里代码修改应该对它关闭 它只需要调用即可。
修订版本
声明抽象图形基类
abstract class Shape2 {
int m_type;
public abstract void draw();
}
继承基类声明子类‘矩形’,‘圆形’,‘三角形’
class Rectangle2 extends Shape2 {
Rectangle2() {
super.m_type = 1;
}
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
class Circle2 extends Shape2 {
Circle2() {
super.m_type = 2;
}
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
class Triangle extends Shape2{
Triangle(){
super.m_type=3;
}
@Override
public void draw() {
System.out.println("绘制三角形");
}
}
定义绘画工具类,编写绘图方法,这里只需要将图形作为参数传入即可调用对应绘制方法
class GraphicEditor2 {
public void drawShape(Shape2 shape) {
shape.draw();
}
}
客户端调用
public class OpenClose2 {
public static void main(String[] args) {
GraphicEditor2 graphicEditor2=new GraphicEditor2();
graphicEditor2.drawShape(new Rectangle2());
graphicEditor2.drawShape(new Circle2());
graphicEditor2.drawShape(new Triangle());
}
}
这样后续若再需要增加图形 只需要新建图像实体 继承图形基类就可以。