如何编写一个遵循 Liskov Substitution 和其他 SOLID 原则而没有代码味道的 ImmutableMap?

How to write an ImmutableMap that follows the Liskov Subsitution and other SOLID principles without code smells?

正在看 ImmutableMap。我建议使用代理模式。

问题是 Map 包含一个 put 方法,它会抛出一个 UnsupportedOperationException。用 ImmutableMap 替换 Map 的其他实例会破坏 Liskov 替换原则。不仅如此,还需要声明putputAll[违反接口隔离原则]

从技术上讲,无法用 ImmutableMap 替换 Map 实例,因为 Map 只是一个接口。所以我的问题是:

使用 Map 接口创建 ImmutableMap 是否会被视为破坏 LSP,因为 Map 包含 putputAll 方法?不实现 Map 会不会被认为是 "Alternative Classes with Different Interfaces" 代码味道?如何创建一个 ImmutableMap 遵守 LSP 但不包含代码味道?

在我看来,ImmutableMap 应该实现 Map。不实现 Map 是个坏主意,因为有许多方法接受 Map 作为参数并且只在只读意义上使用它。我不认为这确实违反了 Liskov 替换原则,因为 Map 的合同清楚地表明 put 是一个可选操作。

实现 Map 的 类 必须实现 put 并不理想,但替代方案是拥有复杂的接口层次结构,每个接口仅包含可能的可选方法。如果有 n 个可选方法,则必须有 2^n 个接口来覆盖所有组合。我不知道n的值,但是有一些不明显的可选操作,比如map.entrySet().iterator()返回的Iterator是否支持setValue操作.如果将此层次结构与实际已经存在的接口层次结构和抽象 类(包括 AbstractMapSortedMapNavigableMapConcurrentMapConcurrentNavigableMap...) 你会一团糟。

所以没有完美的答案,但在我看来最好的解决方案是让 ImmutableMap 实现 Map 并确保你编写的每个方法都带有 Map 作为一个参数清楚地记录了 Map 必须具有的任何属性,以及如果传递了错误类型的 Map 则抛出的异常。