2009-10-05 65 views
1

我有一个抽象类Shape,并且我有一个Canvas对象,Shape用来设置它的位置。我需要确保所有形状都有一个Canvas对象,最好是所有形状中相同的Canvas对象。将资源注入抽象类

我想到了几个选项:

  • 添加画布参数的外形构造(有很多)

  • 有某种形式的地方,抽象的形状得到它的画布(当需要默认时)

  • 使我所有的形状构造都经过某种工厂。

哪一个是最好的?

我使用C#/。NET 3.5

回答

0

依赖注入(DI)的最佳默认模式构造器注入(你的第一个选项),因为它可以很容易地实施,以确保您的形状不变量。

只需添加一个保护条款,以你的外形构造函数是这样的:

private readonly Canvas canvas; 

protected Shape(Canvas canvas) 
{ 
    if(canvas == null) 
    { 
     throw new ArgumentNullException("canvas"); 
    } 
    this.canvas = canvas; 
} 

这确保画布场总是可用,从未空。

您可以通过其他方式实现此属性,但是Constructo Injection是迄今为止确保不变量的最简单方法,所以我总是选择它作为我的默认DI策略,除非我有其他需要。

0

什么具有得到由DI框架注入ICanvas公共财产? 如果你真的有很多实现Shape的类,那就意味着很多带Canvas参数的构造函数,对于你在Shape中声明它的属性并且在任何地方都可以使用它。

0

你有没有想过另一种方式。我的意思是有一个画布对象,然后添加形状对象。这样,所有的形状对象都有一个共同的参考点,即Canvas。一个具有形状集合的画布对象。通过这种方式,您可以对形状执行常见操作,例如调整画布大小时调整所有形状的大小。

0

我也有类似的想法SM卡姆兰:你可以在你的ShapeCanvas属性,来表示该形状属于画布,一个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); 

请注意,ShapeCollectionShape中的嵌套类,因为它是设置私有_canvas属性的唯一方法。

通用集合(如Collection<Shape>)通常用于类似问题,因为您可以覆盖它们的属性以在集合发生更改时添加自定义功能。

您还可以创建一个“空/默认画布”单例,并在形状未分配给实际画布时使用它而不是null(仅用于避免检查Shape.Canvas是否每次都为空)。