我正在尝试使用 SOLID 原则学习更好的编程实践。在这里,我正在研究 Shapes 的示例应用程序。我只想知道,我是否在任何地方违反了原则。下面是类及其代码。
<强>1。基类 - 形状
public abstract class Shape
{
public abstract double Area();
public virtual double Volume()
{
throw new NotImplementedException("You cannot determine volume from here...Method not implemented.");
}
}
<强>2。矩形、三角形等形状的类实现基类形状。
public class Circle : Shape
{
public int Radius { get; set; }
public override double Area() { return 3.14 * Radius * Radius; }
}
public class Triangle : Shape
{
public int Height { get; set; }
public int Base { get; set; }
public override double Area()
{
return 0.5 * Base * Height;
}
}
public class Rectangle : Shape
{
public int Length { get; set; }
public int Breadth { get; set; }
public override double Area()
{
return Length * Breadth;
}
}
public class Square : Shape
{
public Square() { }
public int Side { get; set; }
public override double Area()
{
return Side * Side;
}
}
<强>3。返回 Shape 的工厂类。
internal class ShapeFactory<K, T> where T : class, K, new()
{
static K k;
private ShapeFactory() { }
public static K Create()
{
k = new T();
return k;
}
}
到这里一切似乎都很好,看起来不错,但是当我实现它时出现了问题。我在这里有点困惑。先来看前端代码:
internal class Program
{
private static void Main(string[] args)
{
try
{
var c = ShapeFactory<Shape, Circle>.Create();
// this part is not clear to me. See the questions below
if(c is Circle)
{
var circle = c as Circle;
circle.Radius = 5;
Console.WriteLine(string.Format("{0}", circle.Area()));
}
}
catch (Exception ex)
{
Console.WriteLine("Error: {0}", ex.Message);
}
Console.Read();
}
}
问题
不同的形状有不同的属性,例如圆形有半径,三角形有底边和高度等等,所以我决定将我的属性保留在子类中。我知道,我可以将其作为我的基类中的虚拟成员。那么除了上面的编码还有其他方法吗?
如果不是,那么抽象类有什么用,如果我仍然在将我的 Shape 对象类型转换为 circle 对象?我可以简单地使用 Circle c = new Circle()。我不想要不需要的检查,例如(如果 c 是圆圈)等等。
假设,我被要求实现一种新方法来获取圆的周长。我需要创建一个新的抽象类还是将它放在 Circle 类中。但是如果我把它放在圆上,我认为它会打破 SOLID 的第一个原则,即 SRP . 请注意,我的抽象类不是具有不必要或重复属性的胖类。
提前致谢
最佳答案
我在这种情况下通常做的是在具体类中传递构造函数参数。所以我会将您的具体形状更改为:
public class Circle : Shape
{
public int Radius { get; set; }
public Circle(int radius) {
this.Radius = radius;
}
public override double Area() { return 3.14 * this.Radius * this.Radius; }
}
public class Rectangle : Shape
{
public int Length { get; set; }
public int Breadth { get; set; }
public Rectangle(int lenght, int breadth) {
this.Length = lenght;
this.Breadth = breadth;
}
public override double Area()
{
return Length * Breadth;
}
}
等等
现在,我会使用工厂方法,所以你的 Fabric 现在会像:
public abstract class ShapeFactory
{
abstract Create();
}
public class CircleFactory : ShapeFactory
{
private int radius;
public CircleFactory(int radius){
this.radius = radius;
}
protected override Shape Create()
{
return new Circle(this.radius);
}
}
public class RectangleFactory : ShapeFactory
{
private int length;
private int breadth;
public RectangleFactory(int length, int breadth){
this.lenght = length;
this.breadth = breadth;
}
protected override Shape Create()
{
return new Rectangle(this.length, this.breadth);
}
}
请注意,现在工厂知道如何使用在其自己的构造函数中传递的构造函数来构建形状。
因此,每次您想要不同的形状时,您都将实例化一个新工厂。
ShapeFactory factory = new CircleFactory(5);
Shape shape = factory.Create();
Console.WriteLine(shape.Area()));
我认为这回答了您的第一个和第二个问题。
那么,3: 为了不修改你的类,你可以做的是使用策略模式,以便在运行时传递如何实现这个方法:
public interface IPerimeter
{
int calculatePerimeter();
}
public class Circunference : IPerimeter
{
public int calculatePerimeter(Circle circle) {
return 2*pi*circle.radius;
}
}
public class Circle : Shape
{
public int Radius { get; set; }
private IPerimeter perimeter;
public Circle(int radius, IPerimeter perimeter) {
this.Radius = radius;
this.perimeter = perimeter;
}
public Circunference() {
perimeter.calculatePerimeter(this);
}
public override double Area() { return 3.14 * this.Radius * this.Radius; }
}
希望这对您的培训有所帮助。
关于c# - 这是否违反了我的 SOLID 原则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38090735/