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

时间:2012-08-20 21:23:00

标签: c# design-patterns

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

    OntologyGenerator generator = new OntologyGenerator();
    generator.AddOntologyHeader("Testing");
    generator.AddClassDeclaration(owlBuilder);
    generator.AddSubClass(owlBuilder);
    generator.AddAnnotationAssertions(owlBuilder);

你看到传递的OwlBuilder参数有这样的对象集合:

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

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

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

1 个答案:

答案 0 :(得分:14)

我真的在这里看不到 Template Method 。我看到 Visitor pattern

这是一个例子。

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

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

foreach (var house in houses)
{
    house.Color = Color.Yellow;
}

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

输入访客模式。

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

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);
        }
    }
}

现在我们可以设置我们的房子和我们的房屋清单:

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

public class Houses : VisitableList<House> {}

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

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

简单,优雅,single responsibility(!)

让我们建立房屋:

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 });

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

houses.Accept(new YellowPainter());

......我们所有的房子现在都是黄色的。尼斯!

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

houses.Accept(new AdditionalFloorsBuilder(floors: 2));

或者这个:

owlClasses.Accept(new OwlClassVisitor(owlBuilder, ...));

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