掌握面向对象设计的七大黄金法则

面向对象的七大设计原则是指导面向对象设计和编程的重要准则,它们能够帮助开发者设计出更灵活、可维护、可扩展的软件系统。以下是这七大原则的详细介绍:

1. 单一职责原则(Single Responsibility Principle,SRP)

定义:一个类应该只有一个发生变化的原因,如果有多个原因,那么类就可能需要被拆分。

解释

  • 如果一个类承担了过多的职责,当其中一个职责发生变化时,可能会导致其他职责也受到影响。例如,一个类既负责处理数据,又负责显示数据,那么当显示方式发生变化时,可能会破坏数据处理的逻辑。
  • 遵循单一职责原则可以降低类的复杂度,提高系统的可维护性。

示例

// 违反单一职责原则
class Employee {
    public void calculateSalary() {
        // 计算工资逻辑
    }
    public void printSalary() {
        // 打印工资逻辑
    }
}

// 遵循单一职责原则
class SalaryCalculator {
    public void calculateSalary() {
        // 计算工资逻辑
    }
}
class SalaryPrinter {
    public void printSalary() {
        // 打印工资逻辑
    }
}

2. 开闭原则(Open-Closed Principle,OCP)

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

解释

  • 在不修改已有代码的情况下,通过添加新的代码来实现新功能。这通常是通过抽象化和多态来实现的。
  • 开闭原则的核心在于“对扩展开放,对修改关闭”,即在不改变现有代码的基础上,通过添加新的代码来实现新的功能。

示例

// 违反开闭原则
class Shape {
    public void draw() {
        // 绘制形状逻辑
    }
}
class Circle extends Shape {
    public void draw() {
        // 绘制圆形逻辑
    }
}
class Square extends Shape {
    public void draw() {
        // 绘制正方形逻辑
    }
}

// 遵循开闭原则
interface Shape {
    void draw();
}
class Circle implements Shape {
    public void draw() {
        // 绘制圆形逻辑
    }
}
class Square implements Shape {
    public void draw() {
        // 绘制正方形逻辑
    }
}

3. 里氏替换原则(Liskov Substitution Principle,LSP)

定义:子类对象必须能够替换掉它们的父类对象,并且不破坏系统的正确性。

解释

  • 子类必须完全实现父类的行为,并且不能改变父类原有的行为。如果子类的行为与父类不一致,那么就违反了里氏替换原则。
  • 里氏替换原则是实现开闭原则的重要方式之一,只有当子类可以替换父类时,系统才能在不修改现有代码的情况下扩展新功能。

示例

// 违反里氏替换原则
class Bird {
    public void fly() {
        // 飞行逻辑
    }
}
class Ostrich extends Bird {
    public void fly() {
        // 鸵鸟不会飞,这里违反了父类的行为
    }
}

// 遵循里氏替换原则
class Bird {
    public void move() {
        // 移动逻辑
    }
}
class Ostrich extends Bird {
    public void move() {
        // 鸵鸟通过奔跑移动
    }
}

4. 依赖倒置原则(Dependency Inversion Principle,DIP)

定义:高层模块不应依赖于低层模块,二者都应该依赖于抽象;抽象不应依赖于细节,细节应依赖于抽象。

解释

  • 高层模块和低层模块之间应该通过抽象层进行交互,而不是直接依赖于具体的实现。
  • 依赖倒置原则的核心在于“依赖于抽象,而不是具体实现”,这样可以降低模块之间的耦合度,提高系统的可维护性和可扩展性。

示例

// 违反依赖倒置原则
class LowLevelModule {
    public void doSomething() {
        // 具体实现逻辑
    }
}
class HighLevelModule {
    private LowLevelModule lowLevelModule;
    public HighLevelModule(LowLevelModule lowLevelModule) {
        this.lowLevelModule = lowLevelModule;
    }
    public void performAction() {
        lowLevelModule.doSomething();
    }
}

// 遵循依赖倒置原则
interface LowLevelInterface {
    void doSomething();
}
class LowLevelModule implements LowLevelInterface {
    public void doSomething() {
        // 具体实现逻辑
    }
}
class HighLevelModule {
    private LowLevelInterface lowLevelInterface;
    public HighLevelModule(LowLevelInterface lowLevelInterface) {
        this.lowLevelInterface = lowLevelInterface;
    }
    public void performAction() {
        lowLevelInterface.doSomething();
    }
}

5. 接口分离原则(Interface Segregation Principle,ISP)

定义:不应该强迫客户依赖于它们不使用的方法。

解释

  • 一个类对另一个类的依赖应该建立在最小的接口上,而不是依赖于一个庞大的接口。
  • 接口分离原则的核心在于“接口应该尽可能小”,这样可以避免客户类依赖于不必要的方法,降低系统的耦合度。

示例

// 违反接口分离原则
interface Machine {
    void print();
    void scan();
    void fax();
}
class Printer implements Machine {
    public void print() {
        // 打印逻辑
    }
    public void scan() {
        // 打印机不支持扫描,但必须实现
    }
    public void fax() {
        // 打印机不支持传真,但必须实现
    }
}

// 遵循接口分离原则
interface PrinterInterface {
    void print();
}
interface ScannerInterface {
    void scan();
}
interface FaxInterface {
    void fax();
}
class Printer implements PrinterInterface {
    public void print() {
        // 打印逻辑
    }
}
class Scanner implements ScannerInterface {
    public void scan() {
        // 扫描逻辑
    }
}
class FaxMachine implements FaxInterface {
    public void fax() {
        // 传真逻辑
    }
}

6. 合成复用原则(Composite Reuse Principle,CRP)

定义:尽量使用对象组合,而不是继承来达到复用的目的。

解释

  • 继承是“白箱复用”,子类依赖于父类的实现细节,耦合度高;组合是“黑箱复用”,将已有对象纳入新对象中,耦合度低。
  • 合成复用原则的核心在于“优先使用组合而不是继承”,这样可以降低系统的耦合度,提高系统的可维护性和可扩展性。

示例

// 违反合成复用原则
class Engine {
    public void start() {
        // 发动机启动逻辑
    }
}
class Car extends Engine {
    public void drive() {
        start(); // 直接调用父类方法
    }
}

// 遵循合成复用原则
class Engine {
    public void start() {
        // 发动机启动逻辑
    }
}
class Car {
    private Engine engine;
    public Car(Engine engine) {
        this.engine = engine;
    }
    public void drive() {
        engine.start(); // 通过组合调用
    }
}

7. 迪米特法则(Law of Demeter,LoD)

定义:一个对象应该对其他对象有最少的了解。

解释

  • 一个类应该尽量减少与其他类的直接交互,尽量通过中间类来传递信息。
  • 迪米特法则的核心在于“降低类之间的耦合度”,这样可以提高系统的可维护性和可扩展性。

示例

// 违反迪米特法则
class Department {
    private String name;
    public String getName() {

你可能感兴趣的:(设计模式)