模板方法设计模式是一个很好的选择吗?

Boh*_*ohn 4 c# design-patterns

目前我有一些像这样的代码:

    OntologyGenerator generator = new OntologyGenerator();
    generator.AddOntologyHeader("Testing");
    generator.AddClassDeclaration(owlBuilder);
    generator.AddSubClass(owlBuilder);
    generator.AddAnnotationAssertions(owlBuilder);
Run Code Online (Sandbox Code Playgroud)

您看到传递的OwlBuilder参数的集合具有如下对象的集合:

public class OwlLBuilder: IOwlLBuilder
{
       private ICollection<IOwlClass> owlClasses = new Collection<IOwlClass>();
       private ICollection<IOwlRelation>  owlRelations = new Collection<IOwlRelation> ();
}
Run Code Online (Sandbox Code Playgroud)

所以例如当我说generator.AddClassDeclaration(owlBuilder); 它将循环遍历owlBuilder param的owlClasses集合并为它做一些事情......

我觉得这是一个丑陋的设计.您认为我可以利用修改现有代码来使用模板方法设计模式或您拥有的任何其他更好的设计建议吗?以及一些代码示例,以便我可以全面了解我应该做的事情!

Chr*_*tte 14

我真的看不到这里的模板方法.我看到访客模式.

这是一个例子.

想象一下,你有一堆房子,你需要把它们全部涂成黄色.现在你可以:

var houses = ... a list of houses ...

foreach (var house in houses)
{
    house.Color = Color.Yellow;
}
Run Code Online (Sandbox Code Playgroud)

但是,不是总是把你的房子涂成黄色,你可能希望将这个动作(在这种情况下是绘画)抽象成其他东西.一个解决方案是写一个负责将房子涂成黄色的类.以后这个课程可以替代另一个用不同颜色描绘房子的课程,或者做一些与你的房子完全不同的课程,比如添加另一个楼层!

输入访客模式.

我将展示一些我一直在使用的通用助手类和接口.我喜欢泛型.如果你不这样做,请随意自己动手​​.语义是:"访问者访问访问者","访问者访问访问者".

public interface IVisitor<in T> where T : IVisitable<T>
{
    void Visit(T visitable);
}

public interface IVisitable<out T> where T : IVisitable<T>
{
    void Accept(IVisitor<T> visitor);
}

public abstract class Visitable<T> : IVisitable<T> where T : Visitable<T>
{
    public void Accept(IVisitor<T> visitor)
    {
        visitor.Visit((T)this);
    }
}

public abstract class VisitableList<T> : List<T>, IVisitable<T> where T : Visitable<T>
{
    public void Accept(IVisitor<T> visitor)
    {
        foreach (var item in this)
        {
            item.Accept(visitor);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以设置我们的房子和我们的房屋列表,如下所示:

public class House : Visitable<House>
{
    public Color Color { get; set; }
}

public class Houses : VisitableList<House> {}
Run Code Online (Sandbox Code Playgroud)

现在,访客 - 我们的画家 - 可以访问我们的可访问的房子:

public class YellowPainter : IVisitor<House>
{
    public void Visit(House visitable)
    {
        visitable.Color = Color.Yellow;
    }
}
Run Code Online (Sandbox Code Playgroud)

简单,优雅,单一责任(!).

我们来建房子:

var houses = new Houses();
houses.Add(new House() { Color = Color.Green });
houses.Add(new House() { Color = Color.Blue });
houses.Add(new House() { Color = Color.White });
Run Code Online (Sandbox Code Playgroud)

现在我们准备好把我们所有的房子都画出来.它只需要一个电话:

houses.Accept(new YellowPainter());
Run Code Online (Sandbox Code Playgroud)

......我们所有的房子现在都是黄色的.太好了!

我们可以轻松地做到这一点:

houses.Accept(new AdditionalFloorsBuilder(floors: 2));
Run Code Online (Sandbox Code Playgroud)

或这个:

owlClasses.Accept(new OwlClassVisitor(owlBuilder, ...));
Run Code Online (Sandbox Code Playgroud)

通过这样做,我们已经owlClasses从集合本身的迭代中隔离了每个元素的实际"访问"中发生的事情.访问不需要修改访问.它可以用于仅检查可访问性并使用信息来修改完全不同的内容,例如.你可以用这些信息来喂你的owlBuilder.

  • 确实.对于OP:这里与战略模式有很大的重叠(我个人称之为"YellowPainter"是一个"PaintYellowStrategy".http://en.wikipedia.org/wiki/Strategy_pattern (4认同)
  • 两种模式都支持一种插入行为的方式,而无需修改原始源.在TM中,原始源通常是一个抽象类,它规定了调用语义和顺序.子类紧密耦合到它的基础,这意味着子类可以使用更多与基础交互的方式. (2认同)
  • (续)在V中,访问者"负责",因此控制被反转.访问者也没有强加的语义.但是,与访问者的交互仅限于访问者界面的公共部分.根据您的需要,上面列出的差异(我可能会留下一些重要的差异)可用于向标尺倾斜. (2认同)
  • @neontapir看起来我们达成了协议.要么我们都是对的,要么我们都错了!干杯.;-) (2认同)