SOLID - 单一职责原则和开放/封闭原则是否相互排斥?

ser*_*0ne 5 oop single-responsibility-principle open-closed-principle solid-principles

该单一职责原则指出:

一个班级应该有一个,而且只有一个,改变的理由。

在打开/关闭原则指出:

您应该能够扩展类行为,而无需修改它。

如果一个类应该只有一个改变的理由,但不应该被修改,那么开发人员怎么能同时尊重这两个原则呢?

例子

工厂模式是一个很好的例子,它具有单一职责,但可能违反开放/封闭原则:

public abstract class Product
{
}

public class FooProduct : Product
{
}

public class BarProduct : Product
{
}

public class ProductFactory
{
    public Product GetProduct(string type)
    {
        switch(type)
        {
            case "foo":
                return new FooProduct();
            case "bar":
                return new BarProduct();
            default:
                throw new ArgumentException(...);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我需要ZenProduct在后期添加到工厂时会发生什么?

  • 这肯定违反了开放/封闭原则吗?
  • 我们如何防止这种违规行为?

quj*_*jck 3

这感觉就像是在讨论“扩展类行为”的语义。将新类型添加到工厂是修改现有行为,而不是扩展行为,因为我们没有改变工厂所做的一件事。我们可能需要扩展工厂,但我们还没有扩展它的行为。扩展行为意味着引入新的行为,并且每次创建类型的实例或授权工厂的调用者时都会更符合事件的路线 - 这两个示例都扩展(引入新的)行为。

一个类应该有一个且只有一个改变的理由。

问题中的示例是用于创建Product实例的工厂,其更改的唯一有效原因是更改Product其创建的实例的某些内容,例如添加新的ZenProduct.

您应该能够扩展类的行为而不修改它。

实现这一点的一个非常简单的方法是使用装饰器

装饰器模式对于遵守单一职责原则通常很有用,因为它允许在具有独特关注领域的类之间划分功能。

public interface IProductFactory
{
    Product GetProduct(string type);
}

public class ProductFactory : IProductFactory
{
    public Product GetProduct(string type)
    {
        \\ find and return the type
    }
}

public class ProductFactoryAuth : IProductFactory
{
    IProductFactory decorated;
    public ProductFactoryAuth(IProductFactory decorated)
    {
        this.decorated = decorated;
    }

    public Product GetProduct(string type)
    {
        \\ authenticate the caller
        return this.decorated.GetProduct(type);
    }
}
Run Code Online (Sandbox Code Playgroud)

应用 SOLID 原则时,装饰器模式是一种强大的模式。在上面的示例中,我们在ProductFactory不更改ProductFactory.