C#面向对象编程中开闭原则的示例详解

C#面向对象编程中开闭原则的示例详解

目录

开闭原则

C# 示例

改进

总结

在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解、灵活和可维护。这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原则的子集,在他2000年的论文《设计原则与设计模式》中首次提出。

SOLID 原则包含:

S:单一功能原则(single-responsibility principle)

O:开闭原则(open-closed principle)

L:里氏替换原则(Liskov substitution principle)

I:接口隔离原则(Interface segregation principle)

D:依赖反转原则(Dependency inversion principle)

本文我们来介绍开闭原则。

开闭原则

在面向对象编程领域中,开闭原则 (open-closed principle, OCP) 规定软件中的对象(类,模块,函数等等)应该对于扩展是开放的,而对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。该特性在产品化的环境中是特别有价值的,在这种环境中,改变源代码需要代码审查,单元测试以及诸如此类的用以确保产品使用品质的过程。遵循开闭原则的代码在扩展时并不发生改变,因此无需这些过程。

具体到类,也就是说,在不修改类本身代码的情况下,应该是可以扩展它的行为的。

C# 示例

让我们回顾一下上一篇文章单一功能原则中提到的 AreaCalculator 类,

class AreaCalculator { private List<object> _shapes; public AreaCalculator(List<object> shapes) { _shapes = shapes; } /// <summary> /// 计算所有形状的面积总和 /// </summary> /// <returns></returns> public double Sum() { List<double> areas = new List<double>(); foreach (var item in _shapes) { if (item is Square s) { areas.Add(Math.Pow(s.SideLength, 2)); } else if (item is Circle c) { areas.Add(Math.PI * Math.Pow(c.Radius, 2)); } } return areas.Sum(); } }

对于上面的计算方法,考虑这样一种场景,用户想要计算一些其它形状的面积总和,比如三角形、矩形、五边形等等…… 您将不得不反复编辑此类以添加更多的 if/else 块,这就违反了开闭原则。

改进

一个更好的做法是,将计算每个形状的面积的逻辑从 AreaCalculator 类中移除,并将其添加到对应每个形状的类中。我们可以定义一个带有 CalcArea 方法的接口 IShape,然后让每个形状都实现这个接口。

接口 IShape:

interface IShape { /// <summary> /// 计算面积 /// </summary> /// <returns></returns> double CalcArea(); }

修改后的 Square 和 Circle 类:

/// <summary> /// 正方形 /// </summary> class Square : IShape { public Square(double length) { SideLength = length; } public double SideLength { get; init; } public double CalcArea() { return Math.Pow(SideLength, 2); } } /// <summary> /// 圆形 /// </summary> class Circle : IShape { public Circle(double radius) { Radius = radius; } public double Radius { get; init; } public double CalcArea() { return Math.PI * Math.Pow(Radius, 2); } }

AreaCalculator 类也要对应做一些修改:

class AreaCalculator { private List<IShape> _shapes; public AreaCalculator(List<IShape> shapes) { _shapes = shapes; } /// <summary> /// 计算面积总和 /// </summary> /// <returns></returns> public double Sum() { List<double> areas = new List<double>(); foreach (var item in _shapes) { areas.Add(item.CalcArea()); } return areas.Sum(); } }

此时,如果我们有一个新的形状需要进行计算,我们可以直接添加一个实现了接口 IShape 的新类,而无需修改 AreaCalculator 类的代码,比如添加一个长方形类:

/// <summary> /// 长方形 /// </summary> class Rectangle : IShape { public Rectangle(double width, double height) { Width = width; Height = height; } public double Width { get; init; } public double Height { get; init; } public double CalcArea() { return Width * Height; } }

处理输出格式的 SumCalculatorOutputter 类同样无需修改:

class SumCalculatorOutputter { protected AreaCalculator _calculator; public SumCalculatorOutputter(AreaCalculator calculator) { _calculator = calculator; } public string String() { return $"Sum of the areas of provided shapes: {_calculator.Sum()}"; } public string JSON() { var data = new { Sum = _calculator.Sum() }; return System.Text.Json.JsonSerializer.Serialize(data); } }

然后,我们修改 Main 方法中的代码来测试一下:

static void Main(string[] args) { var shapes = new List<IShape> { new Circle(2), new Square(5), new Rectangle(2,3) }; var areaCalculator = new AreaCalculator(shapes); var outputer = new SumCalculatorOutputter(areaCalculator); Console.WriteLine(outputer.JSON()); Console.WriteLine(outputer.String()); }

运行一下,输出结果为:

{"Sum":43.56637061435917}
Sum of the areas of provided shapes: 43.56637061435917

现在,这些类的设计,既遵循了单一功能原则,又遵循了开闭原则。

总结

本文我介绍了 SOLID 原则中的开闭原则 (open-closed principle),并通过 C# 代码示例简明地诠释了它的含意和实现,希望对您有所帮助。

参考文档:

https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design

到此这篇关于C#面向对象编程中开闭原则的示例详解的文章就介绍到这了,更多相关C#开闭原则内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    Python之可迭代对象、迭代器、生成器

    Python之可迭代对象、迭代器、生成器,迭代,生成器,一、概念描述可迭代对象就是可以迭代的对象,我们可以通过内置的iter函数获取其迭代器,可

    应用程序对象

    应用程序对象,,应用程序对象是一个应用程序级对象,用于在所有用户之间共享信息,并且在Web应用程序运行期间可以保存数据。 应用的性质: 方法

    Java创建对象的几种方式

    Java创建对象的几种方式,对象,方法,本文目录Java创建对象的几种方式java中几种创建对象的方式1Java中创建对象的集中方式有那些JAVA创建对

    wps快速的编辑图层|WPS巧用对象图层

    wps快速的编辑图层|WPS巧用对象图层,图层,编辑,快速,wps,1.WPS 如何巧用对象图层一、认识对象图层工具及按纽1、您可以在插件工具栏中可以

    foreach的用法c语言和c#

    foreach的用法c语言和c#,数组,遍历,本文目录foreach的用法c语言和c#详细讲解foreach循环的用法C#中的foreach 怎么用啊foreach用法C#中的f

    空对象快捷键|空白对象快捷键

    空对象快捷键|空白对象快捷键,,空白对象快捷键以win7系统为例1.在键盘上找到Ctrl➕alt➕delete同时按下2.出现下图界面后,在右下角找到红色