「全网最细 + 实战源码案例」设计模式——六大设计原则

简介: 本文介绍了面向对象设计中的六大原则,旨在提高软件系统的可维护性、可复用性和可拓展性。这些原则包括:开闭原则(OCP)、里氏代换原则(LSP)、依赖倒转原则(DIP)、接口隔离原则(ISP)、迪米特法则(LoD)和合成复用原则(CARP)。每项原则通过具体示例展示了如何通过抽象、多态、组合等方式降低耦合度,增强系统的灵活性与稳定性,从而提升开发效率并降低成本。

目的

提高软件系统的可维护性和可复用性,增加软件的可拓展性和灵活性,程序员遵循 6 条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。


开闭原则(OCP)

核心思想

1. 对拓展开放

  • 软件模块应该在不修改原有代码的情况下,通过扩展的方式增加新功能。
  • 目标:提高系统的可拓展性,适应不断变化的需求。

2. 对修改关闭

  • 在新增需求时,尽量避免修改现有代码。
  • 目标:降低由于修改代码引发的潜在问题,提高系统的稳定性。

实现方式

1. 使用抽象

  • 通过定义接口或抽象类,让具体实现依赖于抽象,而不是直接依赖具体类。
  • 增加新功能时,实现新的子类,不需要修改原有类。

2. 多态机制

  • 借助继承与多态,在运行时决定调用哪个具体类实现。

示例

AbstractSkin:

// 皮肤抽象类
public abstract class AbstractSkin {

    public abstract void display();

}

DefaultSpecificSkin:

// 默认皮肤
public class DefaultSpecificSkin extends AbstractSkin{

    @Override
    public void display() {
        System.out.println("默认皮肤.....");
    }
}

SupermanSpecificSkin:

// 超级英雄皮肤
public class SupermanSpecificSkin extends AbstractSkin{
    @Override
    public void display() {
        System.out.println("超人皮肤.....");
    }
}

SougouInput:

// 搜狗输入法
public class SougouInput {

    private AbstractSkin skin;

    public void setSkin(AbstractSkin skin) {
        this.skin = skin;
    }

    public void display() {
        skin.display();
    }
}

Client:

public class Client {
    public static void main(String[] args) {

        // 1.创建搜狗输入法对象
        SougouInput input = new SougouInput();

        // 2.创建皮肤对象
//        AbstractSkin skin = new SupermanSpecificSkin();
        AbstractSkin skin = new DefaultSpecificSkin();

        // 3.设置皮肤
        input.setSkin(skin);

        // 4.显示皮肤
        input.display();
    }
}

里氏代换原则(LSP)

核心思想

子类对象应该能够替代父类对象出现在程序中的位置,并且程序的行为不会因此受到影响。(一个程序使用父类的对象,那么在不改变程序行为的前提下,子类对象可以替代父类对象)。


实现方式

1. 子类不应该改变父类方法的预期行为,尽量保留父类的方法逻辑。

2. 方法的输入输出应符合父类的契约,子类应遵循父类的行为约定。

3. 使用接口或抽象类设计,可以减少子类对父类的依赖。

4. 确保子类与父类的行为一致性,避免引入错误或不一致的行为。


示例

Quadrilateral

// 四边形接口
public interface Quadrilateral {

    double getLength();
    double getWidth();
}

Rectangle

// 矩形类
public class Rectangle implements Quadrilateral{
    private double length;
    private double width;

    public void setLength(double length) {
        this.length = length;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    @Override
    public double getLength() {
        return length;
    }

    @Override
    public double getWidth() {
        return width;
    }
}

Square

public class Square implements Quadrilateral{

    private double side;

    public double getSide() {
        return side;
    }

    public void setSide(double side) {
        this.side = side;
    }

    @Override
    public double getLength() {
        return side;
    }

    @Override
    public double getWidth() {
        return side;
    }
}

RectangleDemo

public class RectangleDemo {

    public static void main(String[] args) {

        // 1.创建长方形对象
        Rectangle rectangle = new Rectangle();

        // 2.设置长和宽
        rectangle.setLength(20);
        rectangle.setWidth(10);

        // 3.调用扩宽方法
        resize(rectangle);

        // 4.打印长和宽
        printLengthAndWidth(rectangle);
    }

    // 扩宽方法
    public static void resize(Rectangle rectangle){
        while (rectangle.getLength() >= rectangle.getWidth()){
            rectangle.setWidth(rectangle.getWidth() + 1);
        }
    }

    // 打印长和宽
    public static void printLengthAndWidth(Quadrilateral quadrilateral){
        System.out.println("长:" + quadrilateral.getLength() + " 宽:" + quadrilateral.getWidth());
    }

}

依赖倒转原则(DIP)

核心思想:

  • 高层模块(负责实现核心业务逻辑的模块)不应该依赖低层模块(负责实现具体的细节,比如数据存储、网络通信),二者应该依赖抽象。
  • 抽象(接口或抽象类)不应该依赖细节(具体实现类),细节应该依赖抽象。
  • 若没有遵循 DIP,高层模块直接依赖于低层模块,使得两者耦合度变高,且低层模块的变化可能会直接影响到高层模块,从而增加了系统的复杂性和维护难度。
  • DIP 的关键在于,将高层模块与低层模块之间的依赖关系通过抽象接口或抽象类来分离,从而减少直接耦合,增加系统的灵活性。

示例

CPU

// 抽象CPU接口
public interface CPU {
    // 运行cpu
    void run();
}

HardDisk

// 硬盘接口
public interface HardDisk {

    // 存储数据
    void save(String data);
    // 获取数据
    String get();
}

Memory

// 内存条接口
public interface Memory {

    void save();
}

IntelCpu

// 英特尔CPU
public class IntelCpu implements CPU{
    @Override
    public void run() {
        System.out.println("英特尔CPU运行");
    }
}

XiJieHardDisk

// 希捷硬盘
public class XiJieHardDisk implements HardDisk{
    @Override
    public void save(String data) {
        System.out.println("希捷硬盘保存数据为:" + data);
    }

    @Override
    public String get() {
        System.out.println("希捷硬盘读取数据");
        return "数据";
    }
}

KingstonMemory

// 金士顿内存条
public class KingstonMemory implements Memory{
    @Override
    public void save() {
        System.out.println("金士顿内存条");
    }
}

Computer

public class Computer {

    private HardDisk hardDisk;
    private CPU cpu;
    private Memory memory;

    public HardDisk getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }

    public CPU getCpu() {
        return cpu;
    }

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public Memory getMemory() {
        return memory;
    }

    public void setMemory(Memory memory) {
        this.memory = memory;
    }

    // 运行计算机
    public void run() {
        System.out.println("计算机开始运行...");
        String data = hardDisk.get();
        System.out.println("从硬盘中获取数据:" + data);
        cpu.run();
        memory.save();
    }
}

ComputerDemo

public class ComputerDemo {

    public static void main(String[] args) {

        // 1.创建计算机对象
        Computer computer = new Computer();

        // 2.创建计算机组件对象
        HardDisk hardDisk = new XiJieHardDisk();
        CPU cpu = new IntelCpu();
        Memory memory = new KingstonMemory();

        // 3.设置计算机组件
        computer.setHardDisk(hardDisk);
        computer.setCpu(cpu);
        computer.setMemory(memory);

        // 4.运行计算机
        computer.run();
    }
}

接口隔离原则(ISP)

核心思想

  • 不应该强迫一个类依赖于它不需要的接口。(客户端不应被迫实现它不使用的方法)
  • 接口的设计应该小而精,每个接口只包含一组相关的功能,避免一个大型接口包含不相关的方法,从而导致实现类必须实现他们(即使不需要)
  • 这个原则旨在通过拆分接口,使得类只依赖于它实际需要的接口,避免出现类与接口之间的强耦合。

示例


迪米特法则(LoD)

核心思想

  • 一个对象应该对其他对象有最少的了解,即一个对象应该只和它直接相关的对象进行交互,而不应该依赖于它的“朋友”的“朋友”或其他间接对象。
  • 又称最少知识原则,如果两个软件实体无需直接通信,那么就不应该发生直接的相互调用,可以通过第三方转发该调用,以此降低类之间的耦合度,提高模块的相对独立性。
  • 直接的朋友对象:
    • 当前对象本身
    • 当前对象的成员对象
    • 当前对象所创建的对象
    • 当前对象的方法参数等
    • 同当前对象存在关联、聚合和组合关系的对象。

示例


合成复用原则(CARP)

核心思想:

  • 尽量使用对象的组合(聚合)来实现功能复用,而不是通过继承来扩展功能。
  • 组合:一个对象作为另一个对象的成员,通过成员变量引用实现功能的复用。
  • 聚合:一个对象与另一个对象之间通过外部关联实现松散耦合,体现的是“部分-整体”关系。
  • 继承虽是一种复用代码的有效手段,但它是一种强耦合的复用方式,子类过多依赖父类实现,导致灵活性降低。
  • 组合/聚合可以使模块间的耦合度降低,组件可以自由组合,从而提高系统的可扩展性和可维护性。

示例

目录
相关文章
|
15天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171335 12
|
18天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150296 32
|
26天前
|
弹性计算 人工智能 安全
对话 | ECS如何构筑企业上云的第一道安全防线
随着中小企业加速上云,数据泄露、网络攻击等安全威胁日益严重。阿里云推出深度访谈栏目,汇聚产品技术专家,探讨云上安全问题及应对策略。首期节目聚焦ECS安全性,提出三道防线:数据安全、网络安全和身份认证与权限管理,确保用户在云端的数据主权和业务稳定。此外,阿里云还推出了“ECS 99套餐”,以高性价比提供全面的安全保障,帮助中小企业安全上云。
201962 14
对话 | ECS如何构筑企业上云的第一道安全防线
|
4天前
|
机器学习/深度学习 自然语言处理 PyTorch
深入剖析Transformer架构中的多头注意力机制
多头注意力机制(Multi-Head Attention)是Transformer模型中的核心组件,通过并行运行多个独立的注意力机制,捕捉输入序列中不同子空间的语义关联。每个“头”独立处理Query、Key和Value矩阵,经过缩放点积注意力运算后,所有头的输出被拼接并通过线性层融合,最终生成更全面的表示。多头注意力不仅增强了模型对复杂依赖关系的理解,还在自然语言处理任务如机器翻译和阅读理解中表现出色。通过多头自注意力机制,模型在同一序列内部进行多角度的注意力计算,进一步提升了表达能力和泛化性能。
|
8天前
|
存储 人工智能 安全
对话|无影如何助力企业构建办公安全防护体系
阿里云无影助力企业构建办公安全防护体系
1253 10
|
10天前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
|
8天前
|
人工智能 自然语言处理 程序员
通义灵码2.0全新升级,AI程序员全面开放使用
通义灵码2.0来了,成为全球首个同时上线JetBrains和VSCode的AI 程序员产品!立即下载更新最新插件使用。
1347 24
|
8天前
|
消息中间件 人工智能 运维
1月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
660 26
1月更文特别场——寻找用云高手,分享云&AI实践
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
|
14天前
|
人工智能 自然语言处理 API
阿里云百炼xWaytoAGI共学课DAY1 - 必须了解的企业级AI应用开发知识点
本课程旨在介绍阿里云百炼大模型平台的核心功能和应用场景,帮助开发者和技术小白快速上手,体验AI的强大能力,并探索企业级AI应用开发的可能性。