初窥设计模式之七大原则(中篇)| 8月更文挑战

270 阅读3分钟

本文讲解设计模式七大原则中的里氏替换原则、开闭原则 我的上一篇博文 讲述了单一职责原则、接口隔离原则、依赖倒转原则

详情可以戳这里:七大原则上篇

现在进入本文的正题

里氏替换原则

里氏 里氏 顾名思义,里氏替换原则是1988年麻省理工以为姓里的女士提出来的

源于对继承的思考

  • 父类中凡是已经实现好的方法,实际上是在设定规范和契约。虽然它并不强制要求所有子类必须遵守这些约定,但是如果子类对这些已经实现了的方法任意修改,则会对整个继承体系造成破坏。
  • 继承在给程序设计带来便利的同时也带来了弊端。若一个类的功能被其他类继承,则当需要对这个类做修改时,必须考虑到所有子类。降低了程序的可移植性,增加了对象间的耦合。
  • 而如何正确的使用继承呢

里氏原则提出

  1. 如果每个类型为T1的对象O1,都有对应类型为T2的对象O2 。使得已T1定义的程序P,将P中的所有对象O1替换为O2时,程序P并没有发生什么变化。那么类型T2是类型T1的子类型,换句话说:所有使用基类的地方必须能透明的使用其子类的对象
  2. 在继承时 子类尽量不要重写父类的方法
  3. 可以通过聚合、组合、依赖 来解决继承问题

开闭原则

基本介绍

  1. 一个软件实体如类、模块、函数,应当对扩展开放(提供方),对修改关闭(使用方)
  2. 当软件需要变化的时候,尽量扩展软件来实现变化,而不是修改现有代码

案例

设计背景: 编写一个绘画程序,通过输入图形的类型绘制对应的图片。并在客户端中调用

反面案例

声明图形基类

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());
    }
}

这样后续若再需要增加图形 只需要新建图像实体 继承图形基类就可以。