开放封闭原则与战略模式问题

时间:2010-12-19 04:25:04

标签: c# design-patterns

我有几个想法,但我想看看SO社区会建议什么。

我有一个抽象类,上面有一个抽象的Calculate方法。我有两个不同的计算实现。这对我来说是尖叫战略模式,但其中一个实现要求设置selected_type变量,因为它在Calculate方法中使用。我想遵循O​​CP,所以我的Calculate方法不应该接受依赖项。

通过NHibernate从DB中检索此类,并且在创建对象之后才会设置selected_type变量。我试图避免使用if语句来设置selected_type,只要它是特定的实现。什么是最好的方式?

这是一个代码示例:

public abstract class TagType
{
        public virtual long id { get; protected set; }
        public virtual string description { get; protected set; }

        protected TagType(){}

        protected TagType(string description)
        {
            this.description = description;
        }

        public abstract decimal Calculate();
}

public class TagTypeImpl1
{
    public virtual int tag_months { get; protected set; }

    protected TagType() { }

    protected TagType(string description, int tag_months): base(description)
    {
        this.tag_months = tag_months;
    }

    public override decimal Calculate()
    {
        return (12*tag_months);
    }
}

public class TagTypeImpl2
{
    public virtual int tag_months { get; protected set; }
    public virtual TagType selected_tag_type { get; protected set; }

    protected TagType() { }

    protected TagType(string description, int tag_months, TagType selected_tag_type): base(description)
    {
        this.tag_months = tag_months;
        this.selected_tag_type = selected_tag_type;
    }

    public override decimal Calculate()
    {
        return selected_tag_type.Calculate() + (12*tag_months);
    }
}

public class ConsumerController
{
    private readonly IRepository<TagType> repository;

    public ConsumerController(IRepository<TagType> repository)
    {
        this.repository = repository;
    }

    public ActionResult Index(long id)
    {
        var tag_type = repository.get(id);

        //If using TagTypeImpl2 then the selected_tag_type variable needs to be set
        //I want to avoid if(tag_type.GetType() == typeof(TagTypeImpl2)) set selected_tag_type
        var result = tag_type.Calculate();

        return Json(new {result});
    }
}

我可能会尝试用这个类做太多的事情,也许持久化的实体类是使用Calculate方法的错误位置,但它似乎是最好的地方,因为它最了解如何进行计算。

2 个答案:

答案 0 :(得分:1)

创建虚拟(可覆盖)函数“Initialize”是否有意义,应该调用从存储库加载的所有tag_type对象,以便它们可以执行参数化构造函数可以执行的默认构造函数跳过的操作?

或者,您是否可以更改默认构造函数以将selected_type初始化为正确的值或某个值,以指示compute方法在使用之前更正它?

答案 1 :(得分:0)

您的班级不负责决定战略需要什么,这是战略的责任。整个想法是,您可以随时调用您使用相同方式的任何策略。

简单地让所有策略实现相同的接口 - 包括selected_type-,但其中一个忽略selected_type,另一个使用它。决定这一点取决于战略本身。

或者,您的策略实现可以具有比界面中定义的更多的属性。如果您可以从类外部初始化策略,并且初始化类对于了解特定实现的更多信息不是问题,那么您可以仅为需要它的特定策略设置属性。前一种解决方案虽然更干净(总是使用相同的界面)。