【问题标题】:Private class data design pattern in JavaJava中的私有类数据设计模式
【发布时间】:2017-03-02 17:31:54
【问题描述】:

我正在阅读关于 私有类数据设计模式 here 的内容,我正在尝试了解它真正能实现什么。

据我了解,私有类数据设计模式是一种结构模式,旨在为类本身重现“只读”属性:虽然“私有”属性仅对类本身可见和可编辑,但“私有类”中的属性数据”根本无法更改(即使是偶然的)。唯一的解决方案是在私有类数据中提供一个 setter,尽管(至少在我看来)如果私有类数据具有所有属性的 setter,那么我们可能会破坏该模式的目的。

假设我的理解是正确的,这就引出了一个问题:即使主类不能改变任何私有类数据的属性,它也可以设置私有类数据本身的引用,用变量填充它它想要改变

换句话说,一个不关心的开发者可能会做这样的事情:

public class MainData {
    int foo;
    int bar;
    public MainData(int foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    } 
    public int getFoo() {return foo;}
    public int getBar() {return bar;}
}
public class Main {
    private MainData mainData;
    public Main(int foo, int bar) {
        this.mainData = new MainData(foo, bar);
    }
    public doSomeWork() {
        //correct behaviour
        this.mainData.getFoo() + this.mainData.getBar();
        //now I want to trick the pattern
        this.mainData = new MainData(this.mainData.getFoo(), this.mainData.getBar()+4);
        //I've changed bar :(
    }
}

由于“readonly”属性不是编译强制的(与 C# 不同,通过 readonly 保留字),在 Java 中,懒惰的开发人员可能会做这样的事情。如果是真的,那我们为什么要使用这种设计模式呢?与其他模式(如单例模式)不同,此模式不强制执行任何操作,那么我们为什么要使用它呢?

  • 如果您能提供使用此模式的示例并具体帮助您解决一些软件问题,那就太好了;
  • 让我们继续使用 Java:我知道在 C# 中一切都容易得多,但是由于 readonly 保留字,这种模式很简单;

感谢您的友好回复!

【问题讨论】:

  • 在您的示例中,当然,在具有私有字段的类中编写代码很容易,但关键是类之外的任何代码都无法更改它。
  • 我认为 Oracle 不会对你的头像感到满意 startups.stackexchange.com/questions/209/…
  • @HRgiger 我想我需要改变那个头像
  • @Zircon:为什么不直接使用 private 修饰符?你不能达到同样的结果吗?有什么区别?
  • 不想让private final MainData mainData解决这个替换问题?

标签: java design-patterns


【解决方案1】:

Private Class Data 的作者说,所谓的模式的意图是:

意图

  • 控制对类属性的写访问
  • 将数据与使用数据的方法分开
  • 封装类数据初始化
  • 在构造函数之后提供新的 final - final 类型

我们来一一看intent

控制对类属性的写访问

我的观点是控制对类属性的写访问只是通过方法和修饰符来完成。 OOP 称之为Encapsulation

将数据与使用它的方法分开

这对我来说没有多大意义,因为面向对象编程意味着将数据和方法结合在一起。一个对象是关于什么的。将数据与使用它的方法分离似乎是一种乏味的方法。

封装类数据初始化

这就是我在构造函数中所做的。我没有看到将此代码移至另一个类的好处。

在构造函数之后提供新类型的final-final

此意图旨在使对数据类的引用成为最终的,但不要使数据类中的属性成为最终的。我想这就是为什么它被称为“新型决赛”的原因。由于数据类只保存数据,方法与数据是分开的,所以如果数据类上没有setter,就不能修改数据。在这种情况下,数据是不可变的。因此,我看不到数据类仅将类的字段设为 final 的好处。

我的结论

我认为这种所谓的模式增加了复杂性而没有太多好处。因此我不会使用它。我称之为“所谓的模式”,因为

In software engineering, a software design pattern is a general reusable solution to a commonly occurring problem

我没有看到常见的问题。

【讨论】:

  • 我可以看到你论点的根源(我发布这个问题是因为我也有它们)。可能这种模式在 Java 中也没有用(就像在 C# 中一样)。也许在其他语言中(也许是 Python?)它可能是有意义的。 Netherless,我将你的答案标记为正确的答案
  • 还有一个只有数据成员没有方法的类会产生“Broken Modularization”的设计气味。见此链接:tusharma.in/smells/BM.html
【解决方案2】:

私有(或内部)类的成员根本不是“只读”的。 通过 setter 方法甚至直接更改它们的值都没有问题。

拥有“只读”成员并不是使用私有类的理由。这样做的一个原因是该类只能在包含(或外部)类的范围内访问。

【讨论】:

  • 对不起,你能说得更具体点吗?根据source making(讨论或问题部分),私有数据类的目的似乎是限制属性的变化,而不是可访问性(UML 图似乎支持我的这个假设)。如果我想减少可访问性,我不应该只使用内部类吗?这样只有主类可以访问成员。
  • 您所指的页面说:“...通过限制属性的可见性来减少属性的曝光”。这并不意味着完全“只读”,只是不太容易访问。一旦(私有)成员在内部类中,它在较小的范围内可见。但仍然可以从内部类内部看到和编辑。
  • 好的,关于内部类的特性我可以同意你的看法。但我仍然无法理解您的回答与我的问题有何关系。即使假设MainData 是一个内部类,一个不关心的开发人员可能会执行我在主要问题中利用的相同技巧(从而使内部类的使用变得毫无意义)(更好的是,它可以直接设置私有成员)。那么我们为什么要使用这种特殊的模式呢?可能我没明白你的意思。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多