65.9K
CodeProject 正在变化。 阅读更多。
Home

SOLID 原则:单一职责原则 -> 是什么、为什么和怎么做。

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (16投票s)

2013年6月26日

CPOL

2分钟阅读

viewsIcon

90351

SOLID 原则:单一职责原则,C# 中的一个简单例子

 

介绍 

本文将解释单一职责原则 (SRP),并展示一个 C# 中的简单例子。

背景

什么

一个类永远不应该有不止一个改变它的理由。SRP 是 SOLID 原则中最简单的,但也是最难做对的原则之一。将职责收集和聚集在一个地方是很常见的事情,并且会自然而然地发生。从彼此分离这些职责是软件设计的真正意义所在。

为什么?

当一个类有多个职责时,也有更多的触发器和原因去改变这个类。在这个上下文中,一个职责等同于“一个改变的原因”。对一个职责的更改可能会损害或抑制该类满足其他职责的能力。这种耦合会导致脆弱的设计,这些设计在更改时会以意想不到的方式崩溃。如果一个类有多个职责,那么这些职责就会耦合在一起。此外,当一个(功能性)职责被分成多个类时,所有属于该职责的类都必须更改。它们被困在变化的链条中。始终尝试给每个类赋予其自身独特的职责。

如何

可以通过为每个职责定义一个类或一个接口来分离职责。这没有任何区别,一个类可以被看作只是代码的容器,比如一个文件或一个库。重要的是职责通过抽象分离,因此可以由该接口的不同使用者实现。

Using the Code

以下 C# 示例展示了一个名为“RectangleShape”的类,它实现了两种方法,一种计算其矩形面积,另一种绘制矩形。当面积计算由于某种原因发生变化或绘制方法需要更改时,例如使用了另一种填充颜色,则整个类都在更改之下。此外,如果属性被修改,它会影响这两种方法。在代码更改之后,该类必须作为一个整体再次进行测试。显然,更改这个类的原因不止一个。

问题

/// <summary>
/// Class calculates the area and can also draw it on a windows form object.
/// </summary>

    public class RectangleShape
    {
        public int Height{ get; set; }
        public int Width { get; set; }
 
        public int Area()
        {
            return Width * Height;
        }
 
        public void Draw(Form form)
        {
            SolidBrush myBrush = new SolidBrush(System.Drawing.Color.Red);
            Graphics formGraphics = form.CreateGraphics();
            formGraphics.FillRectangle(myBrush, new Rectangle(0, 0, Width, Height);
        }
    }   

通常,上述类由像这样的使用者客户端类使用

/// <summary>
/// Consumes the RectangleShape */
/// </summary>
    public class GeometricsCalculator
    {
        public void CalculateArea(RectangleShape rectangleShape)
        {
            int area = rectangleShape.Area();
        }
    }   


/// <summary>
//// Consumes the RectangleShape */
/// </summary>
    public class GraphicsManager
    {
        public Form form {get;set;}

        public void DrawOnScreen(RectangleShape rectangleShape)
        {
            rectangleShape.Draw(form);
        }
    }

解决方案

接下来的类展示了如何分离不同的职责。使用基本编码,不考虑其他 SOLID 原则。它只是展示了如何处理 SRP 原则。RectangleDraw 类现在使用 RectangleShape 实例和一个 Form 对象。

/// <summary>
/// Class calculates the rectangle's area.
/// </summary>
    public class RectangleShape
    {
        public int Height { get; set; }
        public int Width { get; set; }

        public int Area()
        {
            return Width * Height;
        }
    }

/// <summary>
/// Class draws a rectangle on a windows form object.
/// </summary>
    public class RectangleDraw
    {
        public void Draw(Form form, RectangleShape rectangleShape)
        {
            SolidBrush myBrush = new SolidBrush(System.Drawing.Color.Red);
            Graphics formGraphics = form.CreateGraphics();
            formGraphics.FillRectangle(myBrush, 
            new Rectangle(0, 0, rectangleShape.Width,rectangleShape.Height));
        }
    }

以下代码展示了如何使用这两个类

/// <summary>
/// Consumes the RectangleShape */
/// </summary>
    public class GeometricsCalculator
    {
        public void CalculateArea(RectangleShape rectangleShape)
        {
            int area = rectangleShape.Area();
        }
    }

/// <summary>
/// Consumes the RectangleDraw and RectangleShape */
/// </summary>
    public class GraphicsManager
    {
        public Form form { get; set; }
        
        public void DrawOnScreen(RectangleDraw rectangleDraw, RectangleShape rectangleShape)
        {
            rectangleDraw.Draw(form, rectangleShape);
        }
    }      

玩得开心!

© . All rights reserved.