面向对象七大设计原则,看了必会(代码详细版)(上)

简介: 面向对象七大设计原则,看了必会(代码详细版)(上)

咱们首先了解一个单词

solid

这个单词和咱们今天要讲述的七大原则有什么关系?

咱们首先要了解七大原则都有什么?

  1. 单一职责原则 (Single Responsibility Principle)
  2. 开放-关闭原则 (Open-Closed Principle)
  3. 里氏替换原则 (Liskov Substitution Principle)
  4. 接口隔离原则 (Interface Segregation Principle)
  5. 依赖倒转原则 (Dependence Inversion Principle)
  6. 迪米特法则(Law Of Demeter)
  7. 组合/聚合复用原则 (Composite/Aggregate Reuse Principle)

咱们来进行详细的讲解。

1、单一职责原则

定义:

单一职责原则(Single Responsibility Principle,SRP)又称单一功能原则,由罗伯特·C.马丁(Robert C. Martin)于《敏捷软件开发:原则、模式和实践》一书中提出的。这里的职责是指类变化的原因,单一职责原则规定一个类应该有且仅有一个引起它变化的原因,否则类应该被拆分(There should never be more than one reason for a class to change)。

优点:

单一职责原则的核心就是控制类的粒度大小、将对象解耦、提高其内聚性。如果遵循单一职责原则将有以下优点。

1、降低类的复杂度。一个类只负责一项职责,其逻辑肯定要比负责多项职责简单得多。

2、提高类的可读性。复杂性降低,自然其可读性会提高。

3、提高系统的可维护性。可读性提高,那自然更容易维护了。

4、变更引起的风险降低。变更是必然的,如果单一职责原则遵守得好,当修改一个功能时,可以显著降低对其他功能的影响。

类层面:

错误示范:

public class SingleResponsibility1 {
    public static void main(String[] args) {
        Vehicle vehicle = new Vehicle();
        vehicle.run("汽车");
        vehicle.run("飞机");
        vehicle.run("轮船");
    }
}
class Vehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " 在公路运行...");
    }
}
汽车 在公路运行...
飞机 在公路运行...
轮船 在公路运行...

正确示范:

public class SingleResponsibility2 {
    public static void main(String[] args) {
        RoadVehicle roadVehicle = new RoadVehicle();
        roadVehicle.run("汽车");
        AirVehicle airVehicle = new AirVehicle();
        airVehicle.run("飞机");
        WaterVehicle waterVehicle = new WaterVehicle();
        waterVehicle.run("轮船");
    }
}
class RoadVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " 在公路运行...");
    }
}
class AirVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " 在天空运行...");
    }
}
class WaterVehicle {
    public void run(String vehicle) {
        System.out.println(vehicle + " 在水上运行...");
    }
}
汽车 在公路运行...
飞机 在天空运行...
轮船 在水上运行...

接口层面:

我们假设一个场景, 大家一起做家务, 张三扫地, 李四买菜. 李四买完菜回来还得做饭. 这个逻辑怎么实现呢?

错误示范:

/**
 * 做家务
 */
public interface HouseWork {
    // 扫地
    void sweepFloor();
    // 购物
    void shopping();
}
public class Zhangsan implements HouseWork{
    @Override
    public void sweepFloor() {
        // 扫地
    }
    @Override
    public void shopping() {
    }
}
public class Lisi implements HouseWork{
    @Override
    public void sweepFloor() {
    }
    @Override
    public void shopping() {
        // 购物
    }
}

首先定义了一个做家务的接口, 定义两个方法扫地和买菜. 张三扫地, 就实现扫地接口. 李四买菜, 就实现买菜接口. 然后李四买完菜回来还要做饭, 于是就要在接口类中增加一个方法cooking. 张三和李四都重写这个方法, 但只有李四有具体实现.

这样设计本身就是不合理的. 首先: 张三只扫地, 但是他需要重写买菜方法, 李四不需要扫地, 但是李四也要重写扫地方法. 第二: 这也不符合开闭原则. 增加一种类型做饭, 要修改3个类. 这样当逻辑很复杂的时候, 很容易引起意外错误.

上面这种设计不符合单一职责原则, 修改一个地方, 影响了其他不需要修改的地方.

正确示范:

/**
 * 做家务
 */
public interface Hoursework {
}
public interface Shopping extends Hoursework{
    // 购物
    void shopping();
}
public interface SweepFloor extends Hoursework{
    // 扫地
    void sweepFlooring();
}
public class Zhangsan implements SweepFloor{
    @Override
    public void sweepFlooring() {
        // 张三扫地
    }
}
public class Lisi implements Shopping{
    @Override
    public void shopping() {
        // 李四购物
    }
}

上面做家务不是定义成一个接口, 而是将扫地和做家务分开了. 张三扫地, 那么张三就实现扫地的接口. 李四购物, 李四就实现购物的接口. 后面李四要增加一个功能做饭. 那么就新增一个做饭接口, 这次只需要李四实现做饭接口就可以了.

public interface Cooking extends Hoursework{ 
    void cooking();
}
public class Lisi implements Shopping, Cooking{
    @Override
    public void shopping() {
        // 李四购物
    }
    @Override
    public void cooking() {
        // 李四做饭
    }
}

如上, 我们看到张三没有实现多余的接口, 李四也没有. 而且当新增功能的时候, 只影响了李四, 并没有影响张三. 这就是符合单一职责原则. 一个类只做一件事. 并且他的修改不会带来其他的变化.

2、开放-关闭原则 (Open-Closed Principle)

定义

开放封闭原则(OCP,Open Closed Principle)是所有面向对象原则的核心。软件设计本身所追求的目标就是封装变化、降低耦合,而开放封闭原则正是对这一目标的最直接体现。其他的设计原则,很多时候是为实现这一目标服务的.

具体描述

● 对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况。

● 对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对已有代码进行任何修改

为了满足开闭原则,需要对系统进行抽象化设计,抽象化是开闭原则的关键。

示例

错误实例:

public class OpenClosed1 {
    public static void main(String[] args) {
        GraphicEditor graphicEditor = new GraphicEditor();
        graphicEditor.drawShape(new Rectangle());
        graphicEditor.drawShape(new Circle());
        graphicEditor.drawShape(new Triangle());//+新增绘制三角形
    }
}
//这是一个用于绘图的类
class GraphicEditor {
    //接收 Shape 对象,然后根据 type 来绘制不同的图形
    public void drawShape(Shape s) {
        if (s.m_type == 1)
            drawRectangle(s);
        else if (s.m_type == 2)
            drawCircle(s);
        else if (s.m_type == 3)//+新增绘制三角形
            drawTriangle(s);
    }
    //绘制矩形
    public void drawRectangle(Shape r) {
        System.out.println("绘制矩形");
    }
    //绘制圆形
    public void drawCircle(Shape r) {
        System.out.println("绘制圆形");
    }
    //+新增绘制三角形
    public void drawTriangle(Shape r) {
        System.out.println("绘制三角形");
    }
}
class Shape {
    int m_type;
}
//以前就写好的
class Rectangle extends Shape {
    Rectangle() {
        super.m_type = 1;
    }
}
//以前就写好的
class Circle extends Shape {
    Circle() {
        super.m_type = 2;
    }
}
//+新增绘制三角形
class Triangle extends Shape {
    Triangle() {
        super.m_type = 3;
    }
}
绘制矩形
绘制圆形
绘制三角形


相关文章
|
虚拟化
VMware虚拟机和主机互相ping不通排查以及解决
VMware虚拟机和主机互相ping不通排查以及解决
VMware虚拟机和主机互相ping不通排查以及解决
|
消息中间件 Java 中间件
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
消息队列是大型分布式系统不可缺少的中间件,也是高并发系统的基石中间件,所以掌握好消息队列MQ就变得极其重要。接下来我就将从零开始介绍什么是消息队列?消息队列的应用场景?如何进行选型?如何在Spring Boot项目中整合集成消息队列。
26265 10
秒懂消息队列MQ,万字总结带你全面了解消息队列MQ
|
缓存 Linux
CentOS7配置阿里yum源 超详细!!!
CentOS7配置阿里yum源 超详细!!!
34784 2
|
数据可视化 uml
UML图讲解(关联关系,单向关联,双向关联,自关联,组合关系,依赖关系,继承关系,实现关系)
UML图讲解,关联关系,单向关联,双向关联,自关联,组合关系,依赖关系,继承关系,实现关系。
6603 0
UML图讲解(关联关系,单向关联,双向关联,自关联,组合关系,依赖关系,继承关系,实现关系)
|
存储 监控 安全
什么是日志管理,如何进行日志管理?
日志管理是对IT系统生成的日志数据进行收集、存储、分析和处理的实践,对维护系统健康、确保安全及获取运营智能至关重要。本文介绍了日志管理的基本概念、常见挑战、工具的主要功能及选择解决方案的方法,强调了定义管理目标、日志收集与分析、警报和报告、持续改进等关键步骤,以及如何应对数据量大、安全问题、警报疲劳等挑战,最终实现日志数据的有效管理和利用。
2447 0
面向对象七大设计原则,看了必会(代码详细版)(中)
面向对象七大设计原则,看了必会(代码详细版)(中)
|
存储 缓存 JSON
详解HTTP四种请求:POST、GET、DELETE、PUT
【4月更文挑战第3天】
74534 5
详解HTTP四种请求:POST、GET、DELETE、PUT
|
消息中间件 测试技术 领域建模
DDD - 一文读懂DDD领域驱动设计
DDD - 一文读懂DDD领域驱动设计
49291 6
|
设计模式 Oracle 关系型数据库
深入理解合成复用原则(Composition /Aggregate Reuse Principle)
深入理解合成复用原则(Composition /Aggregate Reuse Principle)
863 0
|
存储 Java C++
JVM内存模型和结构详解(五大模型图解)
JVM内存模型和结构详解(五大模型图解)

热门文章

最新文章