C#的七大设计原则是面向对象编程中非常重要的指导原则,它们帮助开发者创建可维护、可扩展、灵活的代码。下面我将详细解释这些原则并提供示例。

SOLID原则

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

定义:一个类应该只有一个引起它变化的原因,即一个类只负责一项职责。
示例

// 不符合SRP
public class User
{
    public void Register() { /* 注册逻辑 */ }
    public void Login() { /* 登录逻辑 */ }
    public void WriteLog() { /* 日志记录 */ }
}
// 符合SRP
public class User
{
    public void Register() { /* 注册逻辑 */ }
    public void Login() { /* 登录逻辑 */ }
}
public class Logger
{
    public void WriteLog() { /* 日志记录 */ }
}

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

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

// 不符合OCP
public class AreaCalculator
{
    public double CalculateArea(object shape)
    {
        if (shape is Rectangle)
        {
            Rectangle r = (Rectangle)shape;
            return r.Width * r.Height;
        }
        else if (shape is Circle)
        {
            Circle c = (Circle)shape;
            return 3.14 * c.Radius * c.Radius;
        }
        // 每次新增形状都需要修改这个类
        return 0;
    }
}
// 符合OCP
public abstract class Shape
{
    public abstract double CalculateArea();
}
public class Rectangle : Shape
{
    public double Width { get; set; }
    public double Height { get; set; }
    
    public override double CalculateArea()
    {
        return Width * Height;
    }
}
public class Circle : Shape
{
    public double Radius { get; set; }
    
    public override double CalculateArea()
    {
        return 3.14 * Radius * Radius;
    }
}

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

定义:子类必须能够替换其基类而不影响程序的正确性。
示例

// 不符合LSP
public class Bird
{
    public virtual void Fly() { Console.WriteLine("Flying"); }
}
public class Penguin : Bird
{
    public override void Fly() 
    { 
        throw new NotSupportedException("Penguins can't fly"); 
    }
}
// 符合LSP
public abstract class Bird
{
    public abstract void Move();
}
public class FlyingBird : Bird
{
    public override void Move() { Console.WriteLine("Flying"); }
}
public class Penguin : Bird
{
    public override void Move() { Console.WriteLine("Swimming"); }
}

4. 接口隔离原则 (Interface Segregation Principle, ISP)

定义:客户端不应该被迫依赖于它不使用的方法。
示例

// 不符合ISP
public interface IWorker
{
    void Work();
    void Eat();
    void Sleep();
}
public class HumanWorker : IWorker
{
    public void Work() { /* 工作 */ }
    public void Eat() { /* 吃饭 */ }
    public void Sleep() { /* 睡觉 */ }
}
public class RobotWorker : IWorker
{
    public void Work() { /* 工作 */ }
    public void Eat() { throw new NotImplementedException(); }
    public void Sleep() { throw new NotImplementedException(); }
}
// 符合ISP
public interface IWorkable
{
    void Work();
}
public interface IFeedable
{
    void Eat();
}
public interface IRestable
{
    void Sleep();
}
public class HumanWorker : IWorkable, IFeedable, IRestable
{
    public void Work() { /* 工作 */ }
    public void Eat() { /* 吃饭 */ }
    public void Sleep() { /* 睡觉 */ }
}
public class RobotWorker : IWorkable
{
    public void Work() { /* 工作 */ }
}

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

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

// 不符合DIP
public class LightBulb
{
    public void TurnOn() { Console.WriteLine("LightBulb on"); }
}
public class Switch
{
    private LightBulb _bulb;
    public Switch() { _bulb = new LightBulb(); }
    public void Press() { _bulb.TurnOn(); }
}
// 符合DIP
public interface ISwitchableDevice
{
    void TurnOn();
}
public class LightBulb : ISwitchableDevice
{
    public void TurnOn() { Console.WriteLine("LightBulb on"); }
}
public class Fan : ISwitchableDevice
{
    public void TurnOn() { Console.WriteLine("Fan on"); }
}
public class Switch
{
    private ISwitchableDevice _device;
    public Switch(ISwitchableDevice device) { _device = device; }
    public void Press() { _device.TurnOn(); }
}

其他两大原则

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

定义:优先使用对象组合而非继承来达到复用的目的。
示例

// 不符合CRP - 使用继承
public class Engine
{
    public void Start() { Console.WriteLine("Engine started"); }
}
public class Car : Engine
{
    public void Drive() { Start(); Console.WriteLine("Car driving"); }
}
// 符合CRP - 使用组合
public class Engine
{
    public void Start() { Console.WriteLine("Engine started"); }
}
public class Car
{
    private Engine _engine;
    public Car() { _engine = new Engine(); }
    public void Drive() { _engine.Start(); Console.WriteLine("Car driving"); }
}

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

定义:一个对象应该对其他对象保持最少的了解,只与直接的朋友通信。
示例

// 不符合LoD
public class Paper
{
    public string Content { get; set; }
}
public class Printer
{
    public void Print(Paper paper)
    {
        Console.WriteLine(paper.Content);
    }
}
public class Person
{
    public Paper Paper { get; set; }
}
public class Office
{
    public void PrintDocument(Person person)
    {
        Printer printer = new Printer();
        // 直接访问person的paper的content,违反了迪米特原则
        printer.Print(person.Paper);
    }
}
// 符合LoD
public class Paper
{
    public string Content { get; set; }
    public void Print()
    {
        Console.WriteLine(Content);
    }
}
public class Person
{
    private Paper _paper;
    public Person(Paper paper) { _paper = paper; }
    public void PrintDocument()
    {
        _paper.Print();
    }
}
public class Office
{
    public void PrintDocument(Person person)
    {
        person.PrintDocument();
    }
}

七大设计原则总结表

原则名称 英文名称 核心思想 主要目的 C#实现方式 常见应用场景
单一职责原则 Single Responsibility Principle (SRP) 一个类只负责一项职责 降低类的复杂度,提高可读性和可维护性 将功能拆分到不同的类中 用户管理、日志记录、数据处理等
开放封闭原则 Open-Closed Principle (OCP) 对扩展开放,对修改关闭 提高代码的可扩展性和稳定性 使用抽象类、接口和多态 支付系统、插件架构、算法实现等
里氏替换原则 Liskov Substitution Principle (LSP) 子类必须能替换基类 确保继承的正确性,避免程序错误 正确使用继承,不破坏基类行为 形状计算、动物行为、设备控制等
接口隔离原则 Interface Segregation Principle (ISP) 客户端不应依赖不使用的接口 降低接口的复杂性,提高灵活性 将大接口拆分为小接口 工作流系统、权限管理、设备操作等
依赖倒置原则 Dependency Inversion Principle (DIP) 依赖抽象而非具体实现 降低模块间的耦合度 使用依赖注入、接口编程 数据库访问、服务调用、配置管理等
合成复用原则 Composite Reuse Principle (CRP) 优先使用组合而非继承 提高代码的灵活性和复用性 使用组合关系代替继承关系 引擎系统、UI组件、功能模块等
迪米特原则 Law of Demeter (LoD) 只与直接的朋友通信 降低类之间的耦合度 通过方法调用而非直接访问属性 系统集成、第三方库使用、模块通信等

这些设计原则不是孤立的,它们相互关联、相互支持。在实际开发中,应该根据具体情况灵活应用这些原则,而不是生搬硬套。合理使用这些原则可以帮助我们设计出更加健壮、灵活和可维护的软件系统。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐