面向对象设计的六大原则(SOLID原则)-——开闭原则

这篇具有很好参考价值的文章主要介绍了面向对象设计的六大原则(SOLID原则)-——开闭原则。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

开闭原则(Open-Closed Principle, OCP)是面向对象设计的五大SOLID原则之一。这个原则主张“软件实体(类、模块、函数等)应该对扩展开放,对修改关闭”。也就是说,软件的设计应该允许在不修改原有代码的情况下增加新的功能。这样的设计有助于降低代码的复杂性和维护成本,同时提高系统的可复用性和可维护性。

详细解释

开闭原则强调两点:

  1. 对扩展开放:当需要增加新功能时,应该通过添加新的代码来实现,而不是修改已有的代码。这可以通过使用抽象、接口、继承和多态等面向对象的技术来实现。

  2. 对修改关闭:已有的代码,特别是那些已经经过测试和验证的代码,应该尽量避免修改。这样可以减少引入新bug的风险,同时保持系统的稳定性。

遵循开闭原则可以带来以下好处:

  • 提高可维护性:由于系统对修改关闭,因此可以减少因修改已有代码而引入的错误。
  • 提高可扩展性:系统对扩展开放,使得添加新功能变得更加容易。
  • 降低代码的耦合度:通过抽象和接口来定义系统的行为,可以减少类与类之间的直接依赖,从而降低代码的耦合度。

应用场景及代码示例(C#)

场景1:插件系统

假设我们有一个图像处理系统,我们希望通过插件的方式来添加新的图像处理功能。

代码示例

public interface IImageFilter  
{  
    void ApplyFilter(Image image);  
}  
  
public class BrightnessFilter : IImageFilter  
{  
    public void ApplyFilter(Image image)  
    {  
        // 增加亮度的逻辑  
    }  
}  
  
public class ContrastFilter : IImageFilter  
{  
    public void ApplyFilter(Image image)  
    {  
        // 调整对比度的逻辑  
    }  
}  
  
public class ImageProcessor  
{  
    private List<IImageFilter> filters = new List<IImageFilter>();  
  
    public void AddFilter(IImageFilter filter)  
    {  
        filters.Add(filter);  
    }  
  
    public void ProcessImage(Image image)  
    {  
        foreach (var filter in filters)  
        {  
            filter.ApplyFilter(image);  
        }  
    }  
}  
  
// 使用示例  
var processor = new ImageProcessor();  
processor.AddFilter(new BrightnessFilter());  
processor.AddFilter(new ContrastFilter());  
var image = new Image(); // 假设有一个Image类  
processor.ProcessImage(image);

在这个例子中,ImageProcessor 类对扩展开放,因为我们可以很容易地添加新的滤镜(通过实现 IImageFilter 接口)。同时,它对修改关闭,因为我们不需要修改 ImageProcessor 类来支持新的滤镜。

场景2:策略模式

策略模式是一种常见的设计模式,用于根据不同的情况选择不同的算法或策略。这也符合开闭原则。

代码示例

public interface ISortingStrategy  
{  
    void Sort(List<int> list);  
}  
  
public class BubbleSortStrategy : ISortingStrategy  
{  
    public void Sort(List<int> list)  
    {  
        // 冒泡排序的逻辑  
    }  
}  
  
public class QuickSortStrategy : ISortingStrategy  
{  
    public void Sort(List<int> list)  
    {  
        // 快速排序的逻辑  
    }  
}  
  
public class SortedList  
{  
    private ISortingStrategy sortingStrategy;  
  
    public SortedList(ISortingStrategy sortingStrategy)  
    {  
        this.sortingStrategy = sortingStrategy;  
    }  
  
    public void SetSortingStrategy(ISortingStrategy sortingStrategy)  
    {  
        this.sortingStrategy = sortingStrategy;  
    }  
  
    public void Sort(List<int> list)  
    {  
        sortingStrategy.Sort(list);  
    }  
}  
  
// 使用示例  
var sortedList = new SortedList(new BubbleSortStrategy());  
var numbers = new List<int> { 3, 1, 4, 1, 5, 9 };  
sortedList.Sort(numbers);  
  
// 更换排序策略  
sortedList.SetSortingStrategy(new QuickSortStrategy());  
sortedList.Sort(numbers);
 

在这个例子中,SortedList 类对排序策略的扩展开放,因为我们可以通过实现 ISortingStrategy 接口来添加新的排序算法。同时,它对修改关闭,因为更换排序策略时不需要修改 SortedList 类的内部代码。

当然,开闭原则可以应用于许多不同的场景。以下是一些额外的应用场景示例,以及相应的C#代码:

场景3:日志记录系统

在一个大型系统中,日志记录是非常重要的。你可能想要根据不同的需求添加不同的日志记录器,比如文件日志记录器、控制台日志记录器或数据库日志记录器。通过使用开闭原则,你可以轻松地添加新的日志记录器,而不需要修改现有的日志记录系统。

public interface ILogger  
{  
    void Log(string message);  
}  
  
public class FileLogger : ILogger  
{  
    public void Log(string message)  
    {  
        // 将日志写入文件的逻辑  
    }  
}  
  
public class ConsoleLogger : ILogger  
{  
    public void Log(string message)  
    {  
        Console.WriteLine(message);  
    }  
}  
  
public class LoggingSystem  
{  
    private readonly List<ILogger> loggers = new List<ILogger>();  
  
    public void RegisterLogger(ILogger logger)  
    {  
        loggers.Add(logger);  
    }  
  
    public void Log(string message)  
    {  
        foreach (var logger in loggers)  
        {  
            logger.Log(message);  
        }  
    }  
}  
  
// 使用示例  
var loggingSystem = new LoggingSystem();  
loggingSystem.RegisterLogger(new FileLogger());  
loggingSystem.RegisterLogger(new ConsoleLogger());  
loggingSystem.Log("This is a log message.");

在这个例子中,LoggingSystem 类对日志记录器的扩展开放,因为我们可以实现 ILogger 接口来创建新的日志记录器,并将其注册到系统中。同时,它对修改关闭,因为添加新的日志记录器不需要修改 LoggingSystem 类的代码。

场景4:数据库访问层

在构建应用程序时,你可能需要访问不同的数据库,比如SQL Server、MySQL或Oracle。通过使用开闭原则,你可以设计一个数据库访问层,该层对不同类型的数据库扩展开放,而对现有代码的修改关闭。

代码示例

public interface IDatabase  
{  
    void Connect();  
    void ExecuteQuery(string query);  
    void Close();  
}  
  
public class SqlServerDatabase : IDatabase  
{  
    public void Connect()  
    {  
        // 连接到SQL Server的逻辑  
    }  
  
    public void ExecuteQuery(string query)  
    {  
        // 在SQL Server上执行查询的逻辑  
    }  
  
    public void Close()  
    {  
        // 关闭SQL Server连接的逻辑  
    }  
}  
  
public class MySqlDatabase : IDatabase  
{  
    public void Connect()  
    {  
        // 连接到MySQL的逻辑  
    }  
  
    public void ExecuteQuery(string query)  
    {  
        // 在MySQL上执行查询的逻辑  
    }  
  
    public void Close()  
    {  
        // 关闭MySQL连接的逻辑  
    }  
}  
  
public class DatabaseManager  
{  
    private IDatabase database;  
  
    public DatabaseManager(IDatabase database)  
    {  
        this.database = database;  
    }  
  
    public void PerformQuery(string query)  
    {  
        database.Connect();  
        database.ExecuteQuery(query);  
        database.Close();  
    }  
}  
  
// 使用示例  
var sqlServerDb = new SqlServerDatabase();  
var databaseManager = new DatabaseManager(sqlServerDb);  
databaseManager.PerformQuery("SELECT * FROM Users");  
  
// 切换到MySQL数据库  
var mySqlDb = new MySqlDatabase();  
databaseManager = new DatabaseManager(mySqlDb);  
databaseManager.PerformQuery("SELECT * FROM Users");

在这个例子中,DatabaseManager 类对不同类型的数据库扩展开放,因为我们可以通过实现 IDatabase 接口来创建新的数据库访问类。同时,它对修改关闭,因为切换数据库类型不需要修改 DatabaseManager 类的代码。实际上,在实际应用中,你可能会使用依赖注入框架来动态地注入不同的数据库实现,而不是像示例中那样手动创建和切换它们。

public interface ISortingStrategy { void Sort(List<int> list); } public class BubbleSortStrategy : ISortingStrategy { public void Sort(List<int> list) { // 冒泡排序的逻辑 } } public class QuickSortStrategy : ISortingStrategy { public void Sort(List<int> list) { // 快速排序的逻辑 } } public class SortedList { private ISortingStrategy sortingStrategy; public SortedList(ISortingStrategy sortingStrategy) { this.sortingStrategy = sortingStrategy; } public void SetSortingStrategy(ISortingStrategy sortingStrategy) { this.sortingStrategy = sortingStrategy; } public void Sort(List<int> list) { sortingStrategy.Sort(list); } } // 使用示例 var sortedList = new SortedList(new BubbleSortStrategy()); var numbers = new List<int> { 3, 1, 4, 1, 5, 9 }; sortedList.Sort(numbers); // 更换排序策略 sortedList.SetSortingStrategy(new QuickSortStrategy()); sortedList.Sort(numbers);文章来源地址https://www.toymoban.com/news/detail-838913.html

到了这里,关于面向对象设计的六大原则(SOLID原则)-——开闭原则的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式之美】SOLID 原则之二:开闭原则方法论、开闭原则如何取舍

    具体的说,添加一个新的功能应该是,在已有代码基础上扩展代码(新增模块、类、方法等),而非修改已有代码(修改模块、类、方法等)。 举例说明: 现在,如果我们需要添加一个功能,当每秒钟接口超时请求个数,超过某个预先设置的最大阈值时,我们也要触发告警

    2024年01月25日
    浏览(51)
  • C#设计模式之--六大原则 开闭原则

    设计模式六大原则是单一职责原则、里氏替换原则、依赖倒置原则、接口隔离原则、迪米特法则、开闭原则。它们不是要我们刻板的遵守,而是根据实际需要灵活运用。只要对它们的遵守程度在一个合理的范围内,努为做到一个良好的设计。本文主要介绍一下.NET(C#) 开闭原则

    2024年02月10日
    浏览(48)
  • 面向对象设计原则实验之“接口隔离原则”

    客户端不应该依赖那些它不需要的接口。 实验一 考虑一个安全系统。在这个系统中,有一些Door对象,可以被加锁和解锁,并且Door对象知道自己是开着还是关着。这个Door编码成一个接口,这样客户程序就可以使用那些符合Door接口的对象,而不需要依赖于Door的特定实现。 现

    2024年04月12日
    浏览(51)
  • 【设计模式】面向对象设计八大原则

    (1)依赖倒置原则(DIP) 高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。 抽象(稳定)不应该依赖于变化),实现细节应该依赖于抽象(稳定)。 (2)开放封闭原则(OCP) 对扩展开放,对更改封闭。 类模块应该是可扩展的,但是不可

    2024年02月10日
    浏览(44)
  • 面向对象的设计原则

    设计模式:对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案。每一个设计模式系统地命名、解释和评价了面向对象系统中一个重要的和重复出现的设计 三大特性:封装、继承、多态 接口:若干抽象方法的集合 作用:限制实现接口的类必须按照接口给定的

    2024年02月10日
    浏览(41)
  • 01_面向对象的设计原则

    参考资料: 视频 书籍 《设计模式:可复用面向对象软件的基础》 面对复杂问题如何解决? 分解:分而治之,大问题分解成小问题。 抽象:忽视非本质的细节,处理泛化和理想化的对象模型。 面向对象 从语言实现看,是代码和数据的封装 是一系列的公共接口 某种拥有责任

    2024年02月13日
    浏览(43)
  • 基于面向对象基础设计——里氏替换原则

    在Java中,支持抽象和多态的关键机制之一是继承。正是使用了继承,我们才可以创建实现父类中抽象方法的子类。那么,是什么规则在支配着这种特殊的继承用法呢?最佳的继承层次的特征又是什么呢?在什么情况下会使我们创建的类层次结构掉进不符合开闭原则的陷阱中呢

    2024年02月14日
    浏览(48)
  • 《设计模式的艺术》笔记 - 面向对象设计原则

    1、单一职责原则         一个类只负责单一功能领域中的相应职责。 2、开闭原则         一个软件实体应当对扩展开放,对修改关闭。即软件实体应当尽量在不修改原有代码的情况下进行扩展。 3、里氏代换原则         所有引用基类的地方必须能透明地使用其子类的对

    2024年01月21日
    浏览(59)
  • 软件开发:面向对象设计的七大原则!

    开闭原则、里氏代换原则、迪米特原则(最少知道原则)、单一职责原则、接口分隔原则、依赖倒置原则、组合/聚合复用原则。 开闭原则(The Open-Closed Principle ,OCP) 开闭原则:软件实体(模块,类,方法等)应该对扩展开放,对修改关闭。 概念理解 开闭原则是指在进行面

    2024年02月07日
    浏览(48)
  • C++设计模式_02_面向对象设计原则

    变化是复用的天敌!面向对象设计或者说使用了抽象原则的面向对象设计最大的优势在于#

    2024年02月11日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包