我有一个抽象类Shape,并且我有一个Canvas对象,Shape用来设置它的位置。我需要确保所有形状都有一个Canvas对象,最好是所有形状中相同的Canvas对象。将资源注入抽象类
我想到了几个选项:
添加画布参数的外形构造(有很多)
有某种形式的地方,抽象的形状得到它的画布(当需要默认时)
使我所有的形状构造都经过某种工厂。
哪一个是最好的?
我使用C#/。NET 3.5
我有一个抽象类Shape,并且我有一个Canvas对象,Shape用来设置它的位置。我需要确保所有形状都有一个Canvas对象,最好是所有形状中相同的Canvas对象。将资源注入抽象类
我想到了几个选项:
添加画布参数的外形构造(有很多)
有某种形式的地方,抽象的形状得到它的画布(当需要默认时)
使我所有的形状构造都经过某种工厂。
哪一个是最好的?
我使用C#/。NET 3.5
依赖注入(DI)的最佳默认模式构造器注入(你的第一个选项),因为它可以很容易地实施,以确保您的形状不变量。
只需添加一个保护条款,以你的外形构造函数是这样的:
private readonly Canvas canvas;
protected Shape(Canvas canvas)
{
if(canvas == null)
{
throw new ArgumentNullException("canvas");
}
this.canvas = canvas;
}
这确保画布场总是可用,从未空。
您可以通过其他方式实现此属性,但是Constructo Injection是迄今为止确保不变量的最简单方法,所以我总是选择它作为我的默认DI策略,除非我有其他需要。
什么具有得到由DI框架注入ICanvas公共财产? 如果你真的有很多实现Shape的类,那就意味着很多带Canvas参数的构造函数,对于你在Shape中声明它的属性并且在任何地方都可以使用它。
你有没有想过另一种方式。我的意思是有一个画布对象,然后添加形状对象。这样,所有的形状对象都有一个共同的参考点,即Canvas。一个具有形状集合的画布对象。通过这种方式,您可以对形状执行常见操作,例如调整画布大小时调整所有形状的大小。
我也有类似的想法SM卡姆兰:你可以在你的Shape
类Canvas
属性,来表示该形状属于画布,一个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>
)通常用于类似问题,因为您可以覆盖它们的属性以在集合发生更改时添加自定义功能。
您还可以创建一个“空/默认画布”单例,并在形状未分配给实际画布时使用它而不是null(仅用于避免检查Shape.Canvas
是否每次都为空)。