开闭原则、重构

发布于 2024-08-30 05:00:30 字数 1151 浏览 7 评论 0原文

我正在尝试将 OCP 应用于我的代码片段,该代码片段在当前状态下确实很臭,但我觉得我没有完全完成。

当前代码:

public abstract class SomeObject
{}

public class SpecificObject1 : SomeObject
{}

public class SpecificObject2 : SomeObject
{}


// Smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    if (someObject is SpecificObject1)
    {}
    else if (someObject is SpecificObject2)
    {}
  }
}

这真的很难看,我的新方法如下所示:

// No so smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    throw new Expception("Not allowed!");
  }

  public void Store(SpecificObject1 someObject)
  {}

  public void Store(SpecificObject2 someObject)
  {}

}

当出现新的 SomeObject 类型时,我必须实现该特定对象的方式 已存储,这将破坏 OCP,因为我需要更改模型类。

将存储逻辑移至 SomeObject 也感觉不对,因为那样我会违反 SRP(?),因为在这种情况下,SomeObject 几乎就像 DTO,它的责任不是如何知道存储自身。

如果 SomeObject 出现新的实现,那么谁的存储实现会丢失 由于 Model 类中的 Store 方法出现异常,我会收到一个运行时错误,它也感觉像是代码味道。

的形式

IEnumerable<SomeObject> sequence;

这是因为调用代码将以“我不会知道序列对象的具体类型”

。我似乎无法理解 OCP 的概念。任何人都有任何具体的例子或链接,不仅仅是一些汽车/水果的例子吗?

I'm trying to apply OCP to a code snippet I have that in it's current state is really smelly, but I feel I'm not getting all the way to the end.

Current code:

public abstract class SomeObject
{}

public class SpecificObject1 : SomeObject
{}

public class SpecificObject2 : SomeObject
{}


// Smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    if (someObject is SpecificObject1)
    {}
    else if (someObject is SpecificObject2)
    {}
  }
}

That is really ugly, my new approach looks like this:

// No so smelly code
public class Model
{
  public void Store(SomeObject someObject)
  {
    throw new Expception("Not allowed!");
  }

  public void Store(SpecificObject1 someObject)
  {}

  public void Store(SpecificObject2 someObject)
  {}

}

When a new SomeObject type comes along I must implement how that specific object
is stored, this will break OCP cause I need to alter the Model-class.

To move the store logic to SomeObject also feels wrong cause then I will violate SRP (?), becuase in this case the SomeObject is almost like a DTO, it's resposibility it not how to know to store itself.

If a new implementation to SomeObject comes along who's store implementation is missing
I will get a runtime error due to exception in Store method in Model class, it also feels like a code smell.

This is because calling code will in the form of

IEnumerable<SomeObject> sequence;

I will not know the specific types of the sequence objects.

I can't seem to grasp the OCP-concept. Anyone has any concrete examples or links that is a bit more than just some Car/Fruit example?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九八野马 2024-09-06 05:00:30

我展示的模式尝试为特定对象注册处理程序。必须为可能发生的每种类型的对象注册处理程序。如果没有处理程序可以处理它,则会引发异常。

您可以从您的或其他程序集中动态加载处理程序(实现 IHandler 的所有内容),然后实例化并添加注册它们。因此,为任何类型创建处理程序类就足够了实现SomeObject

public interface IHandler {
    bool TryHandle (SomeObject o); // return true iff handled
}

public class Model
{
    private List<SIandler> _Handlers = new List<IHandlers>();

    // registers a new handler
    public void RegisterHandler (IHandler h) {
        _Handlers.Add(h);
    }

    // this tries to store an object by letting all handlers attempts to store
    public void Store (SomeObject o) {
        foreach (var h in _Handlers) {
            if (h.Store(o)) return;
        }

        // no handler was able to handle the type
        throw new Exception();
    }
}

public class Specific1Handler: IHandler
{
    public bool Handle (SomeObject o) {
        if (o is SpecificType1) {
            /* store... */
            return true; // we handled this object
        } else {
            // we're not qualified
            return false;
        }
    }
}

我相信这会满足您的需求。 (顺便说一句,我不知道这个模式是否有名字,如果有的话我很高兴知道。)

The pattern I'm presenting attemps to register handlers for specific objects. There has to be handler registerd for every type of object that can occur. If no handler could deal with it, an exception is thrown.

You can load handlers (everything that implementes IHandler) dynamically from your or from other assemblies and instantiate and add register them. So it's enough to create a handler class for any type the implements SomeObject.

public interface IHandler {
    bool TryHandle (SomeObject o); // return true iff handled
}

public class Model
{
    private List<SIandler> _Handlers = new List<IHandlers>();

    // registers a new handler
    public void RegisterHandler (IHandler h) {
        _Handlers.Add(h);
    }

    // this tries to store an object by letting all handlers attempts to store
    public void Store (SomeObject o) {
        foreach (var h in _Handlers) {
            if (h.Store(o)) return;
        }

        // no handler was able to handle the type
        throw new Exception();
    }
}

public class Specific1Handler: IHandler
{
    public bool Handle (SomeObject o) {
        if (o is SpecificType1) {
            /* store... */
            return true; // we handled this object
        } else {
            // we're not qualified
            return false;
        }
    }
}

I believe this would fit your needs. (By the way, I don't know if this pattern has a name, would be glad to learn if there is one.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文