在层次结构中为每个类创建一个对象实例

Mas*_*ief 6 java oop class-design

采访中有人问我这个问题。

有3个课程AB extends AC extends B。我们必须设计符合这些约束的这些类

  • 客户只能使用其默认构造函数和关键字实例化的一个实例A,一个实例B和一个实例。Cnew
  • 尝试创建这些类中任何一个的另一个实例将导致异常。
  • 该类的设计者必须强制执行上述2条规则,以便客户可以隐式地体验上述规则(即,不应该由客户负责遵守上述规则)。

我建议使用的方法static Map<Class, Object>。因此,例如有人打电话new B()时会检查是否map.contains(B.class)。如果是,则引发异常;如果不是,则将实例保存在map中,并创建对象。

但是下一个问题是,我将如何在每个班级上实施这种方法?按照我的方法,每个构造函数都必须仔细填充地图,否则它将打破约束。

我该如何解决这个问题?

Gho*_*ica 7

但是,下一个问题是,我将如何在每个班级实施这种方法?按照我的方法,每个构造函数都必须仔细填充地图,否则它将打破约束。

只需将地图及其周围的代码放入一些不同的Utility类即可。这样您的每个类都可以执行以下操作:

public WhateverClassConstructor() {
  synchroized(someLock) {
     SingeltonChecker.ensureUnique(this);
Run Code Online (Sandbox Code Playgroud)

 public static void ensureUnique(Object objectToAdd) {
   Class<?> classToAdd = o.getClass();
   ...
Run Code Online (Sandbox Code Playgroud)

考虑到C扩展了B扩展了A的事实,您可能只需要在类A的构造函数中进行调用。另一方面,想象一下您的第一次调用会new C()导致C构造函数发生异常,而第二次调用不会。当然,这本身就是一个问题,但是问题仍然存在:在将对象添加到此类地图之前,如何确保对其进行了完全正确的初始化?

因此:有一的东西写这样实用的代码时需要考虑的。因此,我的答案将集中于给定设计点的不切实际,几乎愚蠢的问题,并建议将其丢弃并寻求其他解决方案,例如简单的事情:

public enum SingletonObjectHolder {
  private final Object hold;
  A_INSTANCE(new A()), B_INSTANCE(new B())...

  public Object getSingleton() { return hold; }
  private SingletonObjectHolder(Object o) { hold = o };
Run Code Online (Sandbox Code Playgroud)

真正的目的不要让自己陷入困境时,不要浪费太多时间尝试给人们提供技术答案。不要误会:获得该地图为基础的“单身”的方针,工作稳健和正确的,对于各种环境中的,认为真的很难

换句话说:如果我在面试中问你这个问题,我想听听一个挑战那个可怕设计点的答案。当然,您花费了10%的时间来概述针对给定方案的解决方案。但是,请花90%的时间解释为什么它是如此糟糕,以及为什么其他解决方案会更好。