C#?實例解釋面向?qū)ο缶幊讨械膯我还δ茉瓌t(示例代碼)
在面向?qū)ο缶幊填I(lǐng)域中,單一功能原則(Single responsibility principle)規(guī)定每個類都應(yīng)該有且僅有一個單一的功能,并且該功能應(yīng)該由這個類完全封裝起來。
在面向?qū)ο缶幊讨?,SOLID 是五個設(shè)計原則的首字母縮寫,旨在使軟件設(shè)計更易于理解、靈活和可維護。這些原則是由美國軟件工程師和講師羅伯特·C·馬丁(Robert Cecil Martin)提出的許多原則的子集,在他2000年的論文《設(shè)計原則與設(shè)計模式》中首次提出。
SOLID 原則包含:
- S:單一功能原則(single-responsibility principle)
- O:開閉原則(open-closed principle)
- L:里氏替換原則(Liskov substitution principle)
- I:接口隔離原則(Interface segregation principle)
- D:依賴反轉(zhuǎn)原則(Dependency inversion principle)
本文我們來介紹單一功能原則。
單一功能原則
在面向?qū)ο缶幊填I(lǐng)域中,單一功能原則(Single responsibility principle)規(guī)定每個類都應(yīng)該有且僅有一個單一的功能,并且該功能應(yīng)該由這個類完全封裝起來。所有它的(這個類的)服務(wù)都應(yīng)該嚴密的和該功能平行(功能平行,意味著沒有依賴)。
這個術(shù)語由羅伯特·C·馬丁(Robert Cecil Martin)在他的《敏捷軟件開發(fā),原則,模式和實踐》一書中的一篇名為『面向?qū)ο笤O(shè)計原則』的文章中提出。馬丁表述該原則是基于《結(jié)構(gòu)化分析和系統(tǒng)規(guī)格》一書中的內(nèi)聚原則(Cohesion)之上的。
馬丁把功能(職責(zé))定義為:“改變的原因”,并總結(jié)出一個類或者模塊應(yīng)該有且只有一個改變的原因。一個具體的例子就是,想象有一個用于編輯和打印報表的模塊。這樣的一個模塊存在兩個改變的原因。第一,報表的內(nèi)容可以改變(編輯)。第二,報表的格式可以改變(打印)。這兩方面的改變會因為完全不同的起因而發(fā)生:一個是本質(zhì)的修改,一個是表面的修改。單一功能原則認為這兩方面的問題事實上是兩個分離的功能,因此他們應(yīng)該分離在不同的類或者模塊里。把具有不同的改變原因的事物耦合在一起的設(shè)計是糟糕的。
保持一個類專注于單一功能點的一個重要的原因是,它可以使類更加的健壯?;仡櫳厦娴睦樱绻幸粋€對于報表“編輯”流程的修改,那么將存在極大的危險性,因為假設(shè)這兩個功能存在于同一個類中,修改報表的“編輯”流程會導(dǎo)致公共狀態(tài)或者依賴關(guān)系的改變,從而可能使“打印”功能的代碼無法正常運行。
C# 示例
例如,考慮這樣一個應(yīng)用程序,它接受一組形狀(圓形和正方形),并計算該列表中所有形狀的面積之和。
首先,創(chuàng)建形狀類,并通過構(gòu)造函數(shù)設(shè)置所需的參數(shù)。
對于正方形,需要知道它的邊長:
/// <summary>
/// 正方形
/// </summary>
class Square
{
public Square(double length)
{
SideLength = length;
}
public double SideLength { get; init; }
}對于圓形,需要它的半徑:
/// <summary>
/// 圓形
/// </summary>
class Circle
{
public Circle(double radius)
{
Radius = radius;
}
public double Radius { get; init; }
}接下來,創(chuàng)建 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();
public string Output()
return $"Sum of the areas of provided shapes: {Sum()}";
}要使用 AreaCalculator 類,您需要實例化這個類,并傳入一個形狀列表,并顯示其輸出。
在此,我們傳入一個三個形狀的列表:一個半徑為 2 的圓,一個邊長為 5 的正方形,一個邊長為 6 的正方形。
static void Main(string[] args)
{
var shapes = new List<object> {
new Circle(2),
new Square(5),
new Square(6)
};
var areas = new AreaCalculator(shapes);
Console.WriteLine(areas.Output());
}運行程序,您會看到如下的輸出:
Sum of the areas of provided shapes: 73.56637061435917
輸出正常,但這并不符合單一功能原則。因為 AreaCalculator 類既計算了所有形狀的面積之和,又處理了輸出數(shù)據(jù)的格式。
考慮這樣一個場景,假如想要輸出轉(zhuǎn)換為另一種格式呢,如 JSON。我們就需要去修改 AreaCalculator 類,這樣本來是為了修改輸出數(shù)據(jù)的格式,卻可能會影響到計算的邏輯,這明顯違反了單一功能原則。
正確的示范
AreaCalculator 類應(yīng)該只關(guān)心計算提供的形狀的面積之和,不應(yīng)該關(guān)心輸出什么格式。
下面我們來做一些修改,刪除 AreaCalculator 類中的 Output 方法:
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();
}并新增一個 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 中的調(diào)用:
static void Main(string[] args)
{
var shapes = new List<object> {
new Circle(2),
new Square(5),
new Square(6)
};
var areaCalculator = new AreaCalculator(shapes);
var outputer = new SumCalculatorOutputter(areaCalculator);
Console.WriteLine(outputer.JSON());
Console.WriteLine(outputer.String());
}運行程序,輸出結(jié)果如下:
{"Sum":73.56637061435917}
Sum of the areas of provided shapes: 73.56637061435917
現(xiàn)在,AreaCalculator 類處理計算邏輯,SumCalculatorOutputter 類處理輸出格式,它們各司其職,遵循了單一功能原則。
總結(jié)
本文我介紹了 SOLID 原則中的單一功能原則(single-responsibility principle),并通過 C# 代碼示例簡明地詮釋了它的含意和實現(xiàn),希望對您有所幫助。
參考文檔:
到此這篇關(guān)于C# 實例解釋面向?qū)ο缶幊讨械膯我还δ茉瓌t的文章就介紹到這了,更多相關(guān)C# 面向?qū)ο缶幊淘瓌t內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# DataTable 轉(zhuǎn)換為 實體類對象實例
如果你的實體類與數(shù)據(jù)庫表是完全一致的。上代碼:2013-04-04

