java - 在层次结构中为每个类创建一个对象实例
问题描述
我在一次采访中被问到这个问题。
有 3 个类A
,B extends A
& C extends B
。我们必须设计符合这些约束的这些类
- 客户端只能使用带有关键字的默认构造函数实例化一个实例
A
、一个实例B
和一个实例。C
new
- 尝试创建任何这些类的另一个实例将导致异常。
- 类的设计者必须强制执行以上 2 条规则,以便客户端将隐式体验上述规则(即遵守上述规则不应该是客户端的责任)。
我建议了一种使用static Map<Class, Object>
. 因此,例如,当有人打电话给它时new B()
,它会检查 if map.contains(B.class)
。如果是,则抛出异常;如果不是,则将实例保存在地图中并创建对象。
但下一个问题是我将如何对每个班级实施这种方法?根据我的方法,每个构造函数都必须仔细填充地图,否则它将打破约束。
我将如何解决这个问题?
解决方案
但下一个问题是我将如何对每个班级实施这种方法?根据我的方法,每个构造函数都必须仔细填充地图,否则它将打破约束。
只需将该地图及其周围的代码放入某个不同的实用程序类即可。这样您的每个班级都可以执行以下操作:
public WhateverClassConstructor() {
synchroized(someLock) {
SingeltonChecker.ensureUnique(this);
和
public static void ensureUnique(Object objectToAdd) {
Class<?> classToAdd = o.getClass();
...
鉴于 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 };
不要浪费太多时间试图给人们一个技术性的答案,真正的重点是不要让自己陷入困境。并且不要误会:让基于地图的“单例”方法在各种情况下稳健且正确地工作,真的很难。
换句话说:如果我在采访中问你这个问题,我想听到一个挑战那个可怕的设计点的答案。当然,您花了 10% 的时间为给定场景概述解决方案。但是要花 90% 的时间来解释为什么它如此糟糕,以及为什么其他解决方案会更好。
推荐阅读
- c# - 将数组插入xml文件
- mongodb - 存储大数据并从中生成报告的最佳方式。mongoDb 与弹性搜索
- node.js - AWS 无服务器功能没有响应图像
- php - 多维数组中的 Foreach 不起作用
- nativescript - nativescript - 在 exitEvent 上更改变量
- php - 如何显示selectpicker中存在的动态值?
- java - 依赖项gradle异常的问题
- javascript - 如何使用 axios 使用 Vue.js 创建用户登录页面
- node.js - express-session - req.session 不显示保存的会话
- unicode - 在 PostScript 中显示 Unicode 字符