【问题标题】:Open Closed Principle and Strategy Pattern Question开闭原则与策略模式题
【发布时间】:2010-12-19 04:25:04
【问题描述】:

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

我有一个带有抽象计算方法的抽象类。我有 2 个计算方式不同的实现。这对我来说是一种策略模式,但是其中一个实现需要设置一个 selected_type 变量,因为它在 Calculate 方法中使用。我想遵循 OCP,所以我的计算方法不应该包含依赖项。

这个类是通过 NHibernate 从数据库中检索的,并且 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 方法的错误位置,但它似乎是最好的位置,因为它最了解如何进行计算。

【问题讨论】:

  • 您真的是说selected_type 变量与自己的抽象类属于同一类型吗?所以你想基本上把 TagType 的实例链接在一起?
  • 对于那个实现来说是的,但是会有其他实现不会使用它。该计算只是一个基本示例,它们会更复杂。
  • 即使你为它做了一个特殊情况,selected_type 究竟如何被初始化......你从哪里得到它?需要知道才能知道谁拥有该信息以及可以在何处/何时访问。

标签: c# design-patterns


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    决定策略需要什么不是你的班级的责任,而是策略的责任。整个想法是,您可以始终以相同的方式调用您正在使用的任何策略。

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 2018-05-13
      • 2011-06-28
      • 2010-10-22
      • 2016-12-13
      • 1970-01-01
      • 2018-07-02
      • 2019-01-06
      • 2011-08-17
      相关资源
      最近更新 更多