Open/Closed 原则和违反封装性

Posted

技术标签:

【中文标题】Open/Closed 原则和违反封装性【英文标题】:Open/Closed principle and violation of encapsulation 【发布时间】:2016-09-21 17:48:19 【问题描述】:

请您检查以下代码是否正确?事实上,我在生产代码中发现了类似的东西,我怀疑它是否符合 Open/Closed 原则。

public abstract class CustomClass 

    private ClassThatSetEnvironmentProperty sysProp = new ClassThatSetEnvironmentProperty("SYS_PROPETY", "SYS_PROPERTY_VALUE");

    // some code here

    void setSysProp(ClassThatSetEnvironmentProperty sysProp) 
        this.sysProp = sysProp;
    

我的理解是 setter 仅用于单元测试可能性(模拟ClassThatSetEnvironmentProperty)。但是在这种情况下,setter 允许具体的继承者改变定义的状态。从我的角度来看,它违反了封装。此外,我认为它也违反了开放/封闭原则。坦率地说,我的一些同事持相反的观点。我真的没有太多的经验,所以我很难认出它。请在这里分享您的意见。谢谢。

【问题讨论】:

我更喜欢构造函数注入而不是 setter 注入。 你是对的,我完全同意你的看法。但是目前的情况呢? Open/Closed 原则的定义指出,一个人应该能够在不修改其源代码的情况下改变一个类的行为。在这种情况下,我认为它完全没有违反原则。源代码保持不变,但 sysProp 已更改。 当前案例使用setter注入;我会使用构造函数。你可以让它不可变而不破坏封装。 @christopher 好的,谢谢。但我的理解是ClassThatSetEnvironmentProperty 实例化是在抽象类中定义的,为继承者定义了一部分公共状态。如果属性可以更改,在每个具体类中定义它会更好吗? 【参考方案1】:

这与开闭原则没有直接关系,开闭原则只是意味着要向系统添加新行为,您应该创建一个新的实现类而不是更改旧的实现类。使用抽象类就可以了。

确实违反封装(这是一个不同的原则)的一件事是包可访问的依赖项设置器。您可以通过将其更改为受保护的设置器来解决该问题。然后扩展类可以设置自己的,但外部调用者不能改变你的对象的状态。

protected final void setSysProp(ClassThatSetEnvironmentProperty sysProp) 
    this.sysProp = sysProp;

【讨论】:

我同意。谢谢 Protected 比私有包更少限制(默认)。 @OleV.V.它们的限制不同。受保护确保所有扩展类都可以访问它。对于共享 API,这是一项关键要求。 @SilasReinagel,你我都没有完全理解Controlling Access to Members of a Class。

以上是关于Open/Closed 原则和违反封装性的主要内容,如果未能解决你的问题,请参考以下文章

面向对象特征之封装性

13.10类的设计原则

策略模式

java设计模式之简单工厂模式

低耦合高聚合,封装原则

JavaSE 学习笔记之封装