2

我下午的大部分时间都在阅读开放/封闭原则,但我似乎无法完全理解它。这是我已经阅读过的一些参考文章,似乎我错过了一些东西。

  1. 了解开闭原则
  2. 依赖注入的终结——谁创建了依赖?

假设我有一个基本的通用存储库,它公开了一些最通用的方法,可以满足存储库的任何需求。

存储库

public abstract class Repository<TModel> where TModel : class {
    protected Repository() { }

    public abstract IList<TModel> FilterBy(
        Expression<Func<TModel, bool>> filterExpression);
    public abstract IList<TModel> GetAll();
    public abstract TModel GetById(int id);
    public abstract Save(TModel instance);
}

然后,我希望专攻 ProductRepository。

产品资料库

public abstract class ProductRepository : Repository<Product> {
    protected ProductRepository() : base() { }
}

让我们假设我从这里的基本存储库中获得了我需要的一切。如果是这样,那么我觉得我没有打破开放/封闭原则,因为我没有定义任何新成员或类似的东西。

但是,如果我需要一种特殊的存储库,比如说一个 AlertLevelConfigurationRepository,并且业务需求规定我一次只能拥有一个 AlertLevelConfiguration。因此,存储库需要始终获取当前配置。

警报级别配置存储库

public abstract class AlertLevelConfigurationRepository 
    : Repository<AlertLevelConfiguration> {
    protected AlertLevelConfigurationRepository() : base() { }

    public abstract AlertLevelConfiguration GetCurrent();
} 

现在,我觉得我打破了开放/封闭原则,因为这个新方法,因为这个类是从它的祖先修改后的派生类型。它被修改为存储库的基本定义不提供此GetCurrent方法。此外,我很确定我永远不会使用任何基本方法,除非该Save方法例外,因为更改级别配置可以是可配置的!

最后,我想知道我是否理解开放/封闭原则,不知何故我怀疑我理解。

我想知道这是否是一个违反原则的例子,如果不是,那么我想对原则本身进行一些解释。

4

1 回答 1

3

What you have there looks like the definition of "Open/Closed Principle" - the Repository class is Open to extension, but Closed to modification. You can add new functionality by extending it (in the form of new subclasses) without having to modify the Repository class. Adding the GetCurrent() call to the Alert subclass is part of the "Open to extension" part of the principle.

Open/Closed is about the specific class being Open/Closed, not the entire inheritance hierarchy. You want to write the class once, and only change it for one reason (Single Responsibility Principle).

You raise a separate issue:

"Besides, I'm quite sure I will never use the any of the base method, given the exception of the Save method, since the alter level configuration can be, well, configurable!"

This is a sign of a poorly designed inheritance hierarchy, or choosing to inherit from the incorrect class. If you're inheriting a lot of functionality you don't need or don't want to use, it's not the right base class, or that class is doing too much (Single Responsibility Principle violation).

What you probably want is to encapsulate some of this functionality - like the GetAll() and GetById() calls that your Alert class doesn't need - into separate classes that only the derived classes that need that functionality will take in as dependencies (assuming you're using DI). Or possibly put that functionality into a class that derives from Repository and have classes that need it derive from that class (I'd prefer the Composition solution over the inheritance solution though).

于 2015-01-21T23:49:34.413 回答