设计模式中的六大设计原则
前言
本文主要阐述了设计模式的六大设计原则,掌握6大设计原则是应用23种设计模式的关键
很多讲解设计模式的博主都忽视了设计原则的重要性,大部分讲解都是尽可能让你理解设计模式的基本原理,但在实际的项目开发中,你真的会使用吗?只有熟悉了基本的设计原则,才能设计出易于维护和扩展的软件架构。
在学习设计原则之前,需得对抽象有一定的了解。不管是单个抽象,还是多重抽象,抽象始终是设计原则的核心。实际编程面对需求时,针对某一模块的功能处理,始终把抽象放在心里。抽象学习,参考以下文章:C++抽象类
六大设计原则包括:开闭原则、里氏替换原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特法则。以下分别详细介绍
一、开闭原则OCP
良好的代码设计完成之后,一般是不允许修改的,程序员若要为软件增加新的功能,只能在原来软件设计的基础上进行扩展,这就是“扩展开放,修改封闭”。
实际工作中,开发一个软件系统,按照开发流程,需求分析、方案设计都完成后,代码开发到一半的时候,产品经理告知需求变更,此时已经开发好的功能要删除或者重写吗?最好的模式是已开发功能不动,新增的不影响其它模块,那么在程序开发初期,就需要考虑面对需求的变化,如何保持框架稳定。“多扩展、少修改”的思想是最合适的。
1.定义及目标
定义:
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。
当需求变化时,应通过添加新代码来扩展功能,而非修改已有代码
核心目标:
提高可维护性:减少修改现有代码带来的风险
增强扩展性:新功能通过扩展现有结构实现,而非侵入式修改
降低耦合:通过抽象隔离变化
2.不使用OCP的示例
场景:计算不同形状的面积,需频繁修改已有代码。
代码实现
#include <iostream>
#include <vector>
// 形状类
class Rectangle {
public:
double width;
double height;
};
class Circle {
public:
double radius;
};
// 面积计算器(违反OCP)
class AreaCalculator {
public:
// 每次新增形状都要修改这个类!
double calculateArea(const std::string& shapeType, void* shape) {
if (shapeType == "Rectangle") {
Rectangle* rect = static_cast<Rectangle*>(shape);
return rect->width * rect->height;
} else if (shapeType == "Circle") {
Circle* circle = static_cast<Circle*>(shape);
return 3.14 * circle->radius * circle->radius;
}
return 0;
}
};
int main() {
Rectangle rect{
5.0, 3.0};
Circle circle{
2.0};
AreaCalculator calculator;
std::cout << "Rectangle Area: " << calculator.calculateArea("Rectangle", &rect) << std::endl;
std::cout << "Circle Area: " << calculator.calculateArea("Circle", &circle) << std::endl;
// 问题:新增 Triangle 必须修改 AreaCalculator!
return 0;
}
问题分析:
违反OCP:每次新增形状(如Triangle),必须修改AreaCalculator类。
代码脆弱:if-else逻辑容易出错,且扩展性差。
难以维护:修改旧代码可能引入新Bug。
3.使用OCP的示例
改进方案:通过抽象(多态)支持扩展,不修改已有代码。
代码实现:
#include <iostream>
#include <vector>
#include <memory>
// 抽象基类(对扩展开放)
class Shape {
public:
virtual double area() const = 0; // 纯虚函数
virtual ~Shape() = default; // 虚析构
};
// 具体形状(可无限扩展)
class Rectangle : public Shape {
double width, height;
public:
Rectangle(double w, double h) : width(w), height(h) {
}
double area() const override {
return width * height; }
};
class Circle : public Shape {
double radius;
public:
Circle(double r) : radius(r) {
}
double area() const override {
return 3.14 * radius * radius; }
};
// 新增 Triangle 无需修改 AreaCalculator!
class Triangle : public Shape {
double base, height;
public:
Triangle(double b, double h) : base(b), height(h) {
}
double area() const override {
return 0.5 * base * height; }
};
// 面积计算器(对修改关闭)
class AreaCalculator {
public:
double calculate(const Shape& shape) {
return shape.area(); // 多态调用
}
};
int main() {
std::vector<std::unique_ptr<Shape>> shapes;
shapes.push_back(std::make_unique<Rectangle>(5.0, 3.0));
shapes.push_back(std::make_unique<Circle>(2.0));
shapes.push_back(std::make_unique<Triangle>(4.0, 3.0)); // 新增形状不影响旧代码
AreaCalculator calculator;
for (const auto& shape : shapes) {
std::cout << "Area: " << calculator.calculate(*shape) << std