我有一个抽象类Shape,我有一个Canvas用来设置其位置的Canvas对象。我需要确保所有Shapes都有一个Canvas对象,最好是一个Canvas对象,它与所有形状都是一样。
我想到了几个选择:
将canvas参数添加到Shape构造函数(有很多)
在某种地方抽象Shape获取其画布(当需要默认值时)
让我所有的造型都经过某种工厂。
哪一个最好?
我正在使用C#/ .NET 3.5
答案 0 :(得分:0)
如果拥有由di framework注入的ICanvas公共属性呢? 如果你真的有很多实现Shape的类,那就意味着很多带有Canvas参数的构造函数,对于你在Shape中声明它一次并在任何地方使用它的属性。
答案 1 :(得分:0)
你有没有想过相反的方式。我的意思是有一个画布对象,然后添加形状对象。这样,所有形状对象都有一个共同的参考点,即Canvas。具有形状集合的画布对象。这样,您可以对形状执行常用操作,例如在画布调整大小时调整所有形状的大小。
答案 2 :(得分:0)
对于依赖注入(DI),最好的默认模式是构造函数注入(您的第一个选项),因为它可以轻松实现以确保您的Shapes不变量。
只需在您的Shape ctor中添加一个Guard子句,如下所示:
private readonly Canvas canvas;
protected Shape(Canvas canvas)
{
if(canvas == null)
{
throw new ArgumentNullException("canvas");
}
this.canvas = canvas;
}
这确保了canvas字段始终可用且从不 null。
您可以通过其他方式实现此属性,但Constructo Injection是迄今为止确保不变量的最简单方法,因此除非我有其他需求,否则我总是选择它作为我的默认DI策略。
答案 3 :(得分:0)
我有与SM Kamran类似的想法:您可以在Canvas
类中拥有Shape
属性,以指示该形状所属的画布,以及Shapes
集合中的Canvas
你的interface ICanvas
{
// It's a good thing to use an interface
// in this phase. It will allow you greater
// freedom later.
}
class Canvas : ICanvas
{
private Shape.ShapeCollection _shapes;
public Collection<Shape> Shapes
{
get { return _shapes; }
}
public Canvas()
{
_shapes = new Shape.ShapeCollection(this);
}
}
class Shape
{
public class ShapeCollection : Collection<Shape>
{
private readonly ICanvas _parent;
public ShapeCollection(ICanvas parent)
{
_parent = parent;
}
protected override void InsertItem(int index, Shape item)
{
item._canvas = _parent;
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
this[index]._canvas = null;
base.RemoveItem(index);
}
protected override void SetItem(int index, Shape item)
{
RemoveAt(index);
InsertItem(index, item);
}
protected override void ClearItems()
{
while (this.Count != 0)
this.RemoveAt(this.Count - 1);
}
}
private ICanvas _canvas;
public ICanvas Canvas
{
get { return _canvas; }
}
}
类来保存一组形状:
这是一个简单的例子:
Shape.Canvas
通过向画布添加形状,Canvas canvas = new Canvas();
Shape circle = new Shape();
canvas.Shapes.Add(circle);
属性将自动更新:
ShapeCollection
请注意,Shape
是_canvas
内的嵌套类,因为它是设置私有Collection<Shape>
属性的唯一方法。
通用集合(如InsertItem
)通常用于类似问题,因为您可以覆盖其RemoveItem
/ Shape.Canvas
属性,以便在更改集合时添加自定义功能。
您还可以创建“空/默认画布”单例,并在未将形状分配给真实画布时使用它而不是null(只是为了避免每次都检查{{1}}是否为空)。