我应该打破哪种模式?

时间:2015-05-19 16:07:35

标签: c# inheritance interface

不要重复自己 要么 封装

我们说我创建了以下内容:

  1. 实现IList的接口IMask。
  2. 实施IMask的Cla​​ss Spot。
  3. 一个类标记,包含几个整数和一个Spot作为字段。
  4. 我想让Marker实现IMask接口。但后来我要重复自己(最后检查代码) 或者我可以在Marker公众中找到我的位置。但接下来我会暴露我班级的实施。 或者我可以从Spot继承Spot,但这不是理想的解决方案,因为语义上Marker不是特定类型的Spot。

    如果我创建另一个将Spot作为字段并且我又想要实现IMask接口的类呢? 我会再次重复自己。 那么,我该怎么办?我应该在Spot中公开列表吗?然后将Spot in Marker公之于众? 或者我应该重复这些电话吗?

    interface IMask : IList<Point>
        {
            public void MoveTo(Point newCenter);
            // ... other Methods
        }
    
        public class Spot : IMask
        {
            List<Point> points;
    
            public void DoSpotyStuff()
            {
                // blabla
            }
    
            // Other methods
            // ...
            // Finally the implementation of IMask
            public void MoveTo(Point newCenter)
            {
                // blabla
            }
    
            // And of course the IList methods
            public void Add(Point newPoint)
            {
                points.Add(newPoint);
            }
        }
    
        public class Marker : IMask
        {
            private Spot mySpot;
            private int blargh;
            // Other fields
    
            public void MarkeryMethod()
            {
                // Blabla
            }
    
            // HERE IS THE PROBLEM: Should I do this and repeat myself
            public void MoveTo(Point newCenter) { mySpot.MoveTo(newCenter); }
    
            // And here I'm REALLY starting to repeat myself
            public void Add(Point newPoint) { mySpot.Add(newPoint); }
        }
    

    观察: 接口IMask不是从List继承的。它正在实现IList接口,而这又是implements ICollection, IEnumerable 假设Marker在语义上不是特殊的Spot。所以,即使我可以从Spot继承并解决问题,它也不是最好的解决方案。

3 个答案:

答案 0 :(得分:6)

接口是建立一种契约,它将实现它的类将具有此方法。所以你可以做的是一个实现你的接口的absctract / base类,然后Marker和Spot类可以从基类继承而且你已经设置好了。

public abstract class BaseClass : IMask {...}

public class Marker : BaseClass{...}

public class Spot : BaseClass{...}

答案 1 :(得分:1)

在我看来,您的选择应该基于您对应用程序增长的期望,即向前兼容性。

如果你认为Marker会进化,例如也许有一天它会包含多个Spot,或者多个支持IMask的对象,然后重复自己是要走的路,因为你想要协调调用MoveTo和Add来包含所有对象在Marker中,你会很高兴Marker中有一层间接。

如果您认为Spot会发展,例如如果Spot要添加更多方法,如ChangeSize或Remove,也许最好的做法是将Spot作为Marker的公共属性公开,类型为IMask。这样就可以立即暴露新属性,而无需编写额外的包装代码。

答案 2 :(得分:0)

interface IMask : IList<System.Drawing.Point>
{
    public void MoveTo(System.Drawing.Point newCenter);
    // ...
    public void 
}
public class Mask : IMask
{
    // ...
}
public class Spot
{
    public Mask Mask = new Mask();
    // ...
}
public  class Marker
{
    public Mask Mask = new Mask();
    /// ...
}

为方便起见,您最好使用属性。