设计模式——七大常见设计原则

目录

单一职责原则(SRP)

开闭原则(OCP)

里氏替换原则(LSP)

依赖倒置原则(DIP)

接口隔离原则(ISP)

迪米特法则(LoDge)

合成复用原则(CRP)


设计原则是一套经过长期实践总结的核心指导思想,旨在帮助开发者构建高内聚、低耦合、可复用、可扩展、易维护的软件系统。这些原则是设计模式的灵魂,多数设计模式都是针对某几个设计原则的具体实现的。

单一职责原则(SRP)

核心定义:一个类(模块、函数)应该只有一个引起它变化的原因,即只负责一项明确的职责。

本质:降低类的复杂度,避免"万能类",减少修改带来的连锁反应。若一个类的职责过多,修改其中一个职责时,可能会破坏其他的功能。

java 复制代码
//错误示例
public class Person {
    public void save(){}

    public void sendEmail(){}

    public void sing(){}
}

//正确示例,职责分离
public class PersonSave {
    public void save(){}
}
public class PersonEmail {
    public void sendEmail(){}
}
public class PersonSing {
    public void sing(){}
}

开闭原则(OCP)

核心定义:软件实体应该对扩展开放,对修改关闭。

本质:这是设计模式的核心目标,通过扩展避免修改原有的代码,降低引入bug的风险,同时提高系统的可扩展性。

java 复制代码
//定义基础接口
public interface Person {
    void happy();
}

//具体实现
public class Cat implements Person {
    @Override
    public void happy() {
        System.out.println("喵喵喵");
    }
}
public class Dog implements Person {
    @Override
    public void happy() {
        System.out.println("汪汪汪");
    }
}

里氏替换原则(LSP)

核心定义:所有引用基类(父类、抽象类)的地方,必须能透明地替换成子类的对象,且不会影响原来的程序。

本质:子类不能破坏父类的行为约定。LSP是实现OCP的基础。

java 复制代码
public class Bird {
    public void fly() {
        System.out.println("Bird is flying");
    }
}

// 错误示例:企鹅不能飞
public class Penguin extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Penguins can't fly");
    }
}

// 正确示例:重新设计继承关系
public abstract class Bird {
    public abstract void move();
}

public class FlyingBird extends Bird {
    @Override
    public void move() {
        System.out.println("Flying bird is flying");
    }
}

public class SwimmingBird extends Bird {
    @Override
    public void move() {
        System.out.println("Swimming bird is swimming");
    }
}

依赖倒置原则(DIP)

核心定义:高层模块不能依赖低层模块,都应该依赖抽象。抽象不应该依赖细节,细节应该依赖抽象。

本质:通过依赖抽象而非具体实现,降低模块间的耦合性。

java 复制代码
// 抽象接口
public interface MessageService {
    void sendMessage(String message);
}

// 具体实现
public class EmailService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending email: " + message);
    }
}

public class SMSService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending SMS: " + message);
    }
}

// 高层模块依赖抽象
public class NotificationService {
    private MessageService messageService;
    
    public NotificationService(MessageService messageService) {
        this.messageService = messageService;
    }
    
    public void notify(String message) {
        messageService.sendMessage(message);
    }
}

接口隔离原则(ISP)

核心定义:使用接口的类不应该被迫依赖不需要的方法,每个接口只包含客户端需要的方法。

本质:避免接口污染,客户端实现接口时,需被迫实现用不到的方法,这样既增加冗余代码,又破坏单一职责。SRP针对"类的职责",ISP针对"接口的方法粒度"。

java 复制代码
// 错误示例:接口过于庞大
public interface Worker {
    void work();
    void eat();
    void sleep();
}

// 正确示例:接口分离
public interface Workable {
    void work();
}

public interface Eatable {
    void eat();
}

public interface Sleepable {
    void sleep();
}

public class Human implements Workable, Eatable, Sleepable {
    @Override
    public void work() { /* 工作 */ }
    
    @Override
    public void eat() { /* 吃饭 */ }
    
    @Override
    public void sleep() { /* 睡觉 */ }
}

public class Robot implements Workable {
    @Override
    public void work() { /* 工作 */ }
    // 只实现需要的接口
}

迪米特法则(LoDge)

核心定义:一个对象应该对其他对象保持最少的了解。

本质:降低对象间的耦合度,减少过度交互,若一个对象依赖过多的陌生对象,会导致关系复杂。

java 复制代码
// 错误示例:暴露过多内部细节
public class Student {
    private String name;
    // getters and setters
}

public class Class {
    private List<Student> students;
    
    public List<Student> getStudents() {
        return students;
    }
}

public class School {
    private List<Class> classes;
    
    public void printAllStudents() {
        for (Class cls : classes) {
            for (Student student : cls.getStudents()) { // 违反迪米特法则
                System.out.println(student.getName());
            }
        }
    }
}

// 正确示例:封装内部细节
public class Class {
    private List<Student> students;
    
    public void printStudents() {
        for (Student student : students) {
            System.out.println(student.getName());
        }
    }
}

public class School {
    private List<Class> classes;
    
    public void printAllStudents() {
        for (Class cls : classes) {
            cls.printStudents(); // 只与直接朋友通信
        }
    }
}

合成复用原则(CRP)

核心定义:优先使用合成或聚合实现代码复用,而不是优先使用继承。

本质:避免继承的耦合问题,继承会让子类和父类绑定,而合成、聚合是弱耦合,一个类通过持有另一个类的实例来调用方法,避免继承的局限性。

java 复制代码
// 错误示例:过度使用继承
public class Car {
    public void startEngine() { /* 启动引擎 */ }
    public void stopEngine() { /* 停止引擎 */ }
}

public class ElectricCar extends Car {
    // 继承了不必要的引擎方法
}

// 正确示例:使用组合
public class Engine {
    public void start() { /* 启动 */ }
    public void stop() { /* 停止 */ }
}

public class ElectricMotor {
    public void start() { /* 启动电机 */ }
    public void stop() { /* 停止电机 */ }
}

public class Car {
    private Engine engine;
    
    public Car(Engine engine) {
        this.engine = engine;
    }
    
    public void start() {
        engine.start();
    }
}
相关推荐
佛祖让我来巡山1 小时前
设计模式深度解析:策略模式、责任链模式与模板模式
设计模式·责任链模式·策略模式·模版模式
__万波__2 小时前
二十三种设计模式(三)--抽象工厂模式
java·设计模式·抽象工厂模式
转转技术团队2 小时前
VDOM 编年史
前端·设计模式·前端框架
明洞日记5 小时前
【设计模式手册014】解释器模式 - 语言解释的优雅实现
java·设计模式·解释器模式
ZHE|张恒5 小时前
设计模式(十六)迭代器模式 — 统一访问集合元素的方式,不暴露内部结构
设计模式·迭代器模式
未秃头的程序猿8 小时前
🚀 设计模式在复杂支付系统中的应用:策略+工厂+模板方法模式实战
后端·设计模式
雨中飘荡的记忆9 小时前
深入理解设计模式之单例模式
java·设计模式
8***293111 小时前
能懂!基于Springboot的用户增删查改(三层设计模式)
spring boot·后端·设计模式
在未来等你20 小时前
AI Agent设计模式 Day 19:Feedback-Loop模式:反馈循环与自我优化
设计模式·llm·react·ai agent·plan-and-execute
兵bing1 天前
设计模式-访问者模式
设计模式·访问者模式