C# 设计模式的七大原则

1、单一职责原则-SRP (Single Responsibility Principle)

单一职责原则要求一个类应该只有一个引起变化的原因,即一个类只负责一项功能。这有助于保持类的简洁性和可维护性,降低代码的复杂度。

点击查看 ->【SRP】举例代码
// 交通工具类
public class Vehicle
{
    public string Brand { get; set; } // 品牌
    public string Model { get; set; } // 型号
    public void GasUp(double liters)
    {
        // 加油的实现
    }
}

// 遵循SRP的实现:
// 分离汽车的品牌和型号
public class CarModel
{
    public string Brand { get; set; }
    public string Model { get; set; }
}
 
// 分离汽车的加油功能
public class CarGasStation
{
    public void GasUp(CarModel carModel, double liters)
    {
        // 加油的实现
    }
}

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

开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类。

点击查看 ->【OCP】举例代码
// 定义一个动物接口
public interface IAnimal
{
    void MakeSound();
}
 
// 实现一个具体的动物类 - 狗
public class Dog : IAnimal
{
    public void MakeSound()
    {
        Console.WriteLine("汪汪汪!");
    }
}
 
// 实现一个具体的动物类 - 猫
public class Cat : IAnimal
{
    public void MakeSound()
    {
        Console.WriteLine("喵喵喵!");
    }
}
 
// 使用动物的方法
public class Zoo
{
    public void FeedAnimals(IAnimal[] animals)
    {
        foreach (var animal in animals)
        {
            animal.MakeSound();
        }
    }
}
 
// 在客户端代码中使用
public class Program
{
    static void Main(string[] args)
    {
        IAnimal[] animals = new IAnimal[] { new Dog(), new Cat() };
        Zoo zoo = new Zoo();
        zoo.FeedAnimals(animals);
    }
}

3、里氏替换原则-LSP(Liskov Substitution Principle)

是面向对象设计的基本原则之一。其核心思想是:任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开放封闭原则”的补充。实现“开放封闭原则”的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以“里氏替换原则”是对实现抽象化的具体步骤的规范。

点击查看 ->【LSP】举例代码
// 长方形
public class Rectangle
{
    protected int width; // 宽
    protected int height; // 高
    public virtual int Area() // 计算面积
    {
        return width * height;
    }
}

// 正方形
public class Square : Rectangle
{
    public Square(int size) 
    {
        width = size;
        height = size;
    }
 
    public override int Area()
    {
        return width * height; // 这里不能保证正确性,因为width和height可能被外部修改,导致不相等
    }
}

//在这个例子中,Square类继承自Rectangle类,但是Square类中的Area方法不符合里氏代换原则,因为它可能返回错误的面积值(如果width和height不相等)

//修改后满足LSP的代码可以是:
public class Rectangle
{
    public virtual int Area()
    {
        return width * height;
    }
    protected int width;
    protected int height;
}
 
public class Square : Rectangle
{
    private int side;
    public Square(int size)
    {
        side = size;
    }
 
    public override int Area()
    {
        return side * side; // 正确返回正方形的面积
    }
}


4、依赖反转原则-DIP(Dependence Inversion Principle)

是面向对象编程中的一个基本原则,其核心思想是:要依赖于抽象,不要依赖于具体实现。简单来说,就是要尽量使用接口或抽象类进行变量的类型声明、方法的参数声明、方法的返回类型声明,以及数据类型的转换等,而不是具体的类。

点击查看 ->【DIP】举例代码
// 假设有一个发送消息的接口
public interface ISender
{
    void Send(string message);
}
 
// 具体的邮件发送器
public class EmailSender : ISender
{
    public void Send(string message)
    {
        // 实现发送邮件的逻辑
        Console.WriteLine("Email sent with message: " + message);
    }
}
 
// 具体的短信发送器
public class SmsSender : ISender
{
    public void Send(string message)
    {
        // 实现发送短信的逻辑
        Console.WriteLine("SMS sent with message: " + message);
    }
}
 
// 使用发送器的类
public class Notifier
{
    private ISender sender;
 
    public Notifier(ISender sender)
    {
        this.sender = sender;
    }
 
    public void SendNotification(string message)
    {
        sender.Send(message);
    }
}
 
// 客户端代码
public class Program
{
    public static void Main(string[] args)
    {
        // 使用具体的发送器实例化Notifier
        Notifier notifier = new Notifier(new EmailSender());
        notifier.SendNotification("Welcome to our service!");
 
        // 可以很容易地更换发送器而不影响其他代码
        notifier = new Notifier(new SmsSender());
        notifier.SendNotification("Welcome to our service!");
    }
}

5、接口隔离原则-ISP(Interface Segregation Principle)

这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出,其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。

点击查看 ->【ISP】举例代码
// 假设有一个庞大的接口
public interface IHugeInterface
{
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    // ... 其他方法
}
 
// 使用接口隔离原则重构上面的接口
public interface IInterface1
{
    void Method1();
    void Method2();
}
 
public interface IInterface2
{
    void Method3();
    void Method4();
}
 
// 实现类只需要实现它需要的接口
public class MyClass : IInterface1, IInterface2
{
    public void Method1() { /* 实现 */ }
    public void Method2() { /* 实现 */ }
    public void Method3() { /* 实现 */ }
    public void Method4() { /* 实现 */ }
}
//在这个例子中,IHugeInterface 接口包含了很多方法,但是 MyClass 只需要实现它需要的方法。通过定义多个小接口 IInterface1 和 IInterface2,MyClass 可以只实现它所需要的方法,这样就满足了接口隔离原则。

6、最少知道原则-LKP(Least Knowledge Principle)

又叫做【迪米特法则-LOD(Law Of Demeter)】,为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。

点击查看 ->【LKP】举例代码
public class Computer {
    private CPU cpu;
 
    public Computer() {
        cpu = new CPU();
    }
 
    public void Start() {
        cpu.Process();
    }
}
 
public class CPU {
    public void Process() {
        Console.WriteLine("CPU is processing.");
    }
}
 
public class User {
    public static void Main(string[] args) {
        Computer computer = new Computer();
        computer.Start();
    }
}
//在这个例子中,Computer 类应该尽可能少地了解 CPU 类的实现细节。Computer 类只需要知道 CPU 类提供了一个 Process 方法用于处理任务,而不需要知道 CPU 是如何处理的。这样的设计遵循了最少知识原则,因为 Computer 类尽量减少了对 CPU 类内部细节的了解。

7、合成复用原则-CRP(Composite Reuse Principle)

原则是尽量使用 合成/聚合/组合 的方式,而不是使用继承。

点击查看 ->【CRP】举例代码
public class Component
{
    public void Operation()
    {
        Console.WriteLine("这是一个基础操作。");
    }
}
 
public class CompositeClass
{
    private Component _component;
 
    public CompositeClass()
    {
        _component = new Component();
    }
 
    public void OperationWrapper()
    {
        Console.WriteLine("这是一个封装操作的方法。");
        _component.Operation();
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        CompositeClass composite = new CompositeClass();
        composite.OperationWrapper();
    }
}
//在这个例子中,CompositeClass 类中包含了一个 Component 类的实例 _component。CompositeClass 类通过其方法 OperationWrapper() 封装了对 _component.Operation() 的调用,同时还添加了一些额外的处理逻辑。这样,CompositeClass 复用了 Component 类的功能,而不是通过继承来强制实现。
posted @   天空科技  阅读(34)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示