单一职责原则
单一职责原则指的是一个类只负责一个功能领域中的相应职责。
我们以做一个较为经典的画图工具为例。
namespace 设计模式
{
public enum ShapeType
{
Rectangle,
Circle
}
}
首先用枚举出两个图形,圆形与矩形。
namespace 设计模式
{
public class Circle
{
public string GetPath()
{
return "圆形";
}
}
}
namespace 设计模式
{
public class Rectangle
{
public string GetPath()
{
return "长方形";
}
}
}
圆形与矩形类分别返回圆形与矩形。
namespace 设计模式
{
public class Graphice
{
public void Stroke(ShapeType shape)
{
if (shape == ShapeType.Circle)
{
Rectangle rectangle = new Rectangle();
Console.WriteLine($"描边{rectangle.GetPath()}");
}
else if(shape == ShapeType.Rectangle)//职责不单一,在一个方法中同时实现两个目的
{
Circle circle = new Circle();
Console.WriteLine($"描边{circle.GetPath()}");
}
else
{
Console.WriteLine("不会画");
}
}
public void Fill(ShapeType shape)
{
if (shape == ShapeType.Circle)
{
Rectangle rectangle = new Rectangle();//多次创建同一个类造成代码的冗余
Console.WriteLine($"填充{rectangle.GetPath()}");
}
else if (shape == ShapeType.Rectangle)
{
Circle circle = new Circle();
Console.WriteLine($"填充{circle.GetPath()}");
}
else
{
Console.WriteLine("不会画");
}
}
}
}
最后是代码实现画图功能。
namespace 设计模式
{
class Proglam
{
static void Main(string[] arge)
{
Graphice g = new Graphice();
g.Stroke(ShapeType.Rectangle);
g.Fill(ShapeType.Rectangle);
g.Stroke(ShapeType.Circle);
g.Fill(ShapeType.Circle);
}
}
}
在上述代码中不难看出,该代码显然不符合单一原则。在一个方法中既要画圆形又要画矩形。
同时多次创建同一个类造成代码的冗余。
因此在改进之后
public class Graphice
{
private readonly Rectangle _rectangle = new Rectangle();
private readonly Circle _circle = new Circle();
public void StrokeCircle()
{
Console.WriteLine($"描边{_circle.GetPath()}");
}
public void StrokeRectangle()
{
Console.WriteLine($"描边{_rectangle.GetPath()}");
}
public void FillCircle()
{
Console.WriteLine($"填充{_circle.GetPath()}");
}
public void FillRectangle()
{
Console.WriteLine($"填充{_rectangle.GetPath()}");
}
我们将描边矩形和圆形的分开到两个方法中,但是这样做虽然方法实现了单一,但是此时类的职责不单一
而且每要添加一个图形时,都要创建两个方法
那么最优方法是什么
public abstract class Shape
{
public abstract string GatPath();
}
我们应该改变图形类的方法,首先使用一个抽象类。
public class Circle : Shape
{
public override string GatPath()
{
return "圆形";
}
}
public class Rectangle : Shape
{
public override string GatPath()
{
return "长方形";
}
}
让圆形与矩形都继承自该抽象类。
public class Graphice
{
public void Stroke(Shape shape)
{
string path = shape.GatPath();
Console.WriteLine($"描边{path}");
}
public void Fill(Shape shape)
{
string path = shape.GatPath();
Console.WriteLine($"填充{path}");
}
}
在这里我们将方法一中传递一个枚举到方法中更改为传递一个基类。
至此我们的代码就达成了单一原则。
可能也有人认为在这个类中既要负责描边又要负责填充。这个类的职责并不单一。
我认为这种情况是可以因情况来讨论的。在这个案例中我们可以简单的认为画图工具的描边与填充属于一种职责。