面向对象编程中的五大设计原则-----常看

设计原则:单一职责、开闭原则、里氏替换、接口隔离和依赖倒转原则

面向对象编程中的五大设计原则: 单一职责原则、开闭原则、里氏替换、接口隔离和依赖倒转原则

1. 单一职责原则

  • 一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。
  • 如果一个类承担了过多的职责,那么它的耦合性会变高,修改其中一个职责可能会影响其他职责。
示例
// 违反 单一职责原则 的示例
class Report {
public:
    void generateReport() {
        // 生成报告
    }
    void saveToFile() {
        // 保存报告到文件
    }
};

// 遵循 单一职责原则 的示例
class Report {
public:
    void generateReport() {
        // 生成报告
    }
};

class ReportSaver {
public:
    void saveToFile(const Report& report) {
        // 保存报告到文件
    }
};
优点
  • 提高类的内聚性。
  • 降低类的复杂度,便于维护和测试。

2. 开闭原则

  • 软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
  • 当需求变化时,应该通过扩展来实现新功能,而不是修改现有代码。
示例
// 违反 开闭原则 的示例
class Rectangle {
public:
    double width, height;
};

class AreaCalculator {
public:
    double calculateArea(Rectangle& shape) {
        return shape.width * shape.height;
    }
};

// 如果需要支持圆形,必须修改 AreaCalculator
class Circle {
public:
    double radius;
};

// 遵循 开闭原则 的示例
class Shape {
public:
    virtual double calculateArea() = 0; // 抽象方法
};

class Rectangle : public Shape {
public:
    double width, height;
    double calculateArea() override {
        return width * height;
    }
};

class Circle : public Shape {
public:
    double radius;
    double calculateArea() override {
        return 3.14 * radius * radius;
    }
};
优点
  • 提高代码的可扩展性。
  • 减少对现有代码的修改,降低引入新错误的风险。

3. 里氏替换原则

  • 子类必须能够替换其父类,并且替换后程序的行为不会发生变化。
  • 子类应该完全实现父类的行为,而不是改变父类的行为。
示例
// 违反 里氏替换原则 的示例
class Bird {
public:
    virtual void fly() {
        // 飞行
    }
};

class Penguin : public Bird {
public:
    void fly() override {
        throw std::runtime_error("Penguins can't fly!");
    }
};

// 遵循 里氏替换原则 的示例
class Bird {
public:
    virtual void move() = 0; // 抽象方法
};

class FlyingBird : public Bird {
public:
    void move() override {
        fly();
    }
    virtual void fly() = 0;
};

class Penguin : public Bird {
public:
    void move() override {
        swim();
    }
    void swim() {
        // 游泳
    }
};
优点
  • 确保继承关系的正确性。
  • 增强代码的可复用性和可维护性。

4. 接口隔离原则

  • 客户端不应该依赖它不需要的接口。
  • 应该将大而全的接口拆分为小而专的接口,避免实现类被迫实现不需要的方法。
示例
// 违反 接口隔离原则 的示例
class Machine {
public:
    virtual void print() = 0;
    virtual void scan() = 0;
    virtual void fax() = 0;
};

class MultiFunctionPrinter : public Machine {
public:
    void print() override {
        // 打印
    }
    void scan() override {
        // 扫描
    }
    void fax() override {
        // 传真
    }
};

class SimplePrinter : public Machine {
public:
    void print() override {
        // 打印
    }
    void scan() override {
        throw std::runtime_error("Not supported!");
    }
    void fax() override {
        throw std::runtime_error("Not supported!");
    }
};

// 遵循 接口隔离原则 的示例
class Printer {
public:
    virtual void print() = 0;
};

class Scanner {
public:
    virtual void scan() = 0;
};

class Fax {
public:
    virtual void fax() = 0;
};

class SimplePrinter : public Printer {
public:
    void print() override {
        // 打印
    }
};
优点
  • 减少接口的冗余。
  • 提高代码的灵活性和可维护性。

5. 依赖倒置原则

  • 高层模块不应该依赖低层模块,二者都应该依赖抽象。
  • 抽象不应该依赖细节,细节应该依赖抽象。
示例
// 违反 依赖倒置原则 的示例
class LightBulb {
public:
    void turnOn() {
        // 开灯
    }
};

class Switch {
private:
    LightBulb bulb;
public:
    void operate() {
        bulb.turnOn();
    }
};

// 遵循 依赖倒置原则 的示例
class Switchable {
public:
    virtual void turnOn() = 0;
};

class LightBulb : public Switchable {
public:
    void turnOn() override {
        // 开灯
    }
};

class Switch {
private:
    Switchable& device;
public:
    Switch(Switchable& device) : device(device) {}
    void operate() {
        device.turnOn();
    }
};
优点
  • 降低模块间的耦合性。
  • 提高代码的可扩展性和可维护性。

总结

  • 单一职责原则:一个类只负责一项职责。
  • 开闭原则:对扩展开放,对修改关闭。
  • 里氏替换原则:子类可以替换父类。
  • 接口隔离原则:接口应该小而专。
  • 依赖倒置原则:依赖抽象,而不是具体实现。

遵循 SOLID 原则可以帮助开发者设计出更健壮、灵活和可维护的软件系统。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值