C#面向?qū)ο缶幊讨虚_(kāi)閉原則的示例詳解
在面向?qū)ο缶幊讨校?strong>SOLID 是五個(gè)設(shè)計(jì)原則的首字母縮寫(xiě),旨在使軟件設(shè)計(jì)更易于理解、靈活和可維護(hù)。這些原則是由美國(guó)軟件工程師和講師羅伯特·C·馬丁(Robert Cecil Martin)提出的許多原則的子集,在他2000年的論文《設(shè)計(jì)原則與設(shè)計(jì)模式》中首次提出。
SOLID 原則包含:
- S:單一功能原則(single-responsibility principle)
- O:開(kāi)閉原則(open-closed principle)
- L:里氏替換原則(Liskov substitution principle)
- I:接口隔離原則(Interface segregation principle)
- D:依賴反轉(zhuǎn)原則(Dependency inversion principle)
本文我們來(lái)介紹開(kāi)閉原則。
開(kāi)閉原則
在面向?qū)ο缶幊填I(lǐng)域中,開(kāi)閉原則 (open-closed principle, OCP) 規(guī)定“軟件中的對(duì)象(類,模塊,函數(shù)等等)應(yīng)該對(duì)于擴(kuò)展是開(kāi)放的,而對(duì)于修改是封閉的”,這意味著一個(gè)實(shí)體是允許在不改變它的源代碼的前提下變更它的行為。該特性在產(chǎn)品化的環(huán)境中是特別有價(jià)值的,在這種環(huán)境中,改變?cè)创a需要代碼審查,單元測(cè)試以及諸如此類的用以確保產(chǎn)品使用品質(zhì)的過(guò)程。遵循開(kāi)閉原則的代碼在擴(kuò)展時(shí)并不發(fā)生改變,因此無(wú)需這些過(guò)程。
具體到類,也就是說(shuō),在不修改類本身代碼的情況下,應(yīng)該是可以擴(kuò)展它的行為的。
C# 示例
讓我們回顧一下上一篇文章單一功能原則中提到的 AreaCalculator 類,
class AreaCalculator { private List<object> _shapes; public AreaCalculator(List<object> shapes) { _shapes = shapes; } /// <summary> /// 計(jì)算所有形狀的面積總和 /// </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(); } }
對(duì)于上面的計(jì)算方法,考慮這樣一種場(chǎng)景,用戶想要計(jì)算一些其它形狀的面積總和,比如三角形、矩形、五邊形等等…… 您將不得不反復(fù)編輯此類以添加更多的 if/else
塊,這就違反了開(kāi)閉原則。
改進(jìn)
一個(gè)更好的做法是,將計(jì)算每個(gè)形狀的面積的邏輯從 AreaCalculator 類中移除,并將其添加到對(duì)應(yīng)每個(gè)形狀的類中。我們可以定義一個(gè)帶有 CalcArea
方法的接口 IShape,然后讓每個(gè)形狀都實(shí)現(xiàn)這個(gè)接口。
接口 IShape:
interface IShape { /// <summary> /// 計(jì)算面積 /// </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 類也要對(duì)應(yīng)做一些修改:
class AreaCalculator { private List<IShape> _shapes; public AreaCalculator(List<IShape> shapes) { _shapes = shapes; } /// <summary> /// 計(jì)算面積總和 /// </summary> /// <returns></returns> public double Sum() { List<double> areas = new List<double>(); foreach (var item in _shapes) { areas.Add(item.CalcArea()); } return areas.Sum(); } }
此時(shí),如果我們有一個(gè)新的形狀需要進(jìn)行計(jì)算,我們可以直接添加一個(gè)實(shí)現(xiàn)了接口 IShape 的新類,而無(wú)需修改 AreaCalculator 類的代碼,比如添加一個(gè)長(zhǎng)方形類:
/// <summary> /// 長(zhǎng)方形 /// </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 類同樣無(wú)需修改:
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
方法中的代碼來(lái)測(cè)試一下:
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()); }
運(yùn)行一下,輸出結(jié)果為:
{"Sum":43.56637061435917}
Sum of the areas of provided shapes: 43.56637061435917
現(xiàn)在,這些類的設(shè)計(jì),既遵循了單一功能原則,又遵循了開(kāi)閉原則。
總結(jié)
本文我介紹了 SOLID 原則中的開(kāi)閉原則 (open-closed principle),并通過(guò) C# 代碼示例簡(jiǎn)明地詮釋了它的含意和實(shí)現(xiàn),希望對(duì)您有所幫助。
參考文檔:
到此這篇關(guān)于C#面向?qū)ο缶幊讨虚_(kāi)閉原則的示例詳解的文章就介紹到這了,更多相關(guān)C#開(kāi)閉原則內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#/VB.NET實(shí)現(xiàn)將XML轉(zhuǎn)為PDF
可擴(kuò)展標(biāo)記語(yǔ)言(XML)文件是一種標(biāo)準(zhǔn)的文本文件,它使用特定的標(biāo)記來(lái)描述文檔的結(jié)構(gòu)以及其他特性。本文將利用C#實(shí)現(xiàn)XML文件轉(zhuǎn)PDF?,需要的可以參考一下2022-03-03C#實(shí)現(xiàn)發(fā)送手機(jī)驗(yàn)證碼功能
之前基于c#實(shí)現(xiàn)手機(jī)發(fā)送驗(yàn)證碼功能很復(fù)雜,真正做起來(lái)也就那回事,不過(guò)就是一個(gè)post請(qǐng)求就可以實(shí)現(xiàn)的東西,今天小編把思路分享到腳本之家平臺(tái),供大家參考下2017-06-06C#運(yùn)算符之與,或,異或及移位運(yùn)算小結(jié)
本文是對(duì)C#中的與,或,異或及移位運(yùn)算進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2013-10-10C# 啟動(dòng) SQL Server 服務(wù)的實(shí)例
下面小編就為大家分享一篇C# 啟動(dòng) SQL Server 服務(wù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12