我正在尝试设计几个基础绘图类,我可以从中继承和定义复杂的绘图。
如您所见,LineDrawing
和CompoundDrawing
派生自抽象的Drawing类。 CompoundDrawing
有一个内部List<Drawing>
,它允许我们存储任意数量的Drawing
个对象,并定义更复杂的图形。
public abstract class Drawing
{
public bool CanBeRotated
{
get;
set;
}
private float m_rotation;
public float Rotation
{
get
{
return m_rotation;
}
}
protected Drawing()
{
CanBeRotated = true;
}
public void Rotate(float degree)
{
if (CanBeRotated)
m_rotation = degree;
}
}
public sealed class LineDrawing : Drawing
{
private readonly Line m_line;
public Line Line
{
get
{
return m_line;
}
}
public LineDrawing(Line line)
{
m_line = line;
}
}
public class CompoundDrawing : Drawing
{
protected IList<Drawing> m_drawings;
protected CompoundDrawing(IList<Drawing> drawings)
{
m_drawings = new List<Drawing>(drawings);
}
}
假设我要定义一个派生自CompoundDrawing的RectangleDrawing。
public class RectangleDrawing : CompoundDrawing
{
public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
{
foreach(var line in lineDrawings)
{
line.CanBeRotated = false;
}
}
}
现在我在这里面临一个问题!显然,我不希望这个新类中的LineDrawing对象是可旋转的!但是我不确定在这个模式中我应该设置哪个!
答案 0 :(得分:0)
我会考虑采用不可变的方法:
public abstract class Drawing
{
//some shapes might not be rotable or rotation
//simply doesn't make sense: circle
public virtual bool CanBeRotated => true;
public Drawing Rotate(float degree)
{
//Don't mutate this, return a new
//rotated instance.
if (!CanBeRotated) return this;
return rotate(float);
}
//let each concrete type handle its own rotation.
protected abstract Drawing rotate(float);
//etc.
}
不变性会给你带来什么?好吧,谁在乎是否有人试图旋转你的复合物体的单独线?他们不会改变任何有意义的东西,因为没有什么可以改变,他们只会获得一个不属于原始复合对象的新旋转线。
CompoundDrawing
轮换逻辑相当简单:
protected override Drawing rotate(float degeee)
//Note I'm passing in an IEnumerable<Line> instead of an IList<>
//Why the need of an IList<>, don't burden the API with unecessary
//constraints.
=> new Rectange(lines.Select(l => l.Rotate(degree)));
所有这些都说,我建议您将构建块更改为Point
,Line
似乎是一个奇怪的选择。这样,所有形状都是由特定顺序的点组成的复合图形。绘制任何形状只需按顺序连接点,旋转只需旋转每个点等。
答案 1 :(得分:0)
我将Rotate移动到它自己的界面,因为它不适用于所有类型的绘图。
public interface IRotate
{
void Rotate(float degree);
}
public class SquareDrawing : Drawing, IRotate
{
public void Rotate(float degree)
{
//actual code to rotate the drawing
}
}
public class RectangleDrawing : CompoundDrawing
{
public RectangleDrawing(IList<LineDrawing> lineDrawings) : base(lineDrawings)
{
foreach(var line in lineDrawings)
{
if (line is IRotate)
{
((IRotate)line).Rotate(45.0);
}
}
}
}