如何编写一个遵循 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 替换原则。不仅如此,还需要声明put
和putAll
[违反接口隔离原则]
从技术上讲,无法用 ImmutableMap
替换 Map
实例,因为 Map
只是一个接口。所以我的问题是:
使用 Map
接口创建 ImmutableMap
是否会被视为破坏 LSP,因为 Map
包含 put
和 putAll
方法?不实现 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
操作.如果将此层次结构与实际已经存在的接口层次结构和抽象 类(包括 AbstractMap
、SortedMap
、NavigableMap
、ConcurrentMap
、ConcurrentNavigableMap
...) 你会一团糟。
所以没有完美的答案,但在我看来最好的解决方案是让 ImmutableMap
实现 Map
并确保你编写的每个方法都带有 Map
作为一个参数清楚地记录了 Map
必须具有的任何属性,以及如果传递了错误类型的 Map
则抛出的异常。
我 ImmutableMap
。我建议使用代理模式。
问题是 Map
包含一个 put
方法,它会抛出一个 UnsupportedOperationException
。用 ImmutableMap
替换 Map
的其他实例会破坏 Liskov 替换原则。不仅如此,还需要声明put
和putAll
[违反接口隔离原则]
从技术上讲,无法用 ImmutableMap
替换 Map
实例,因为 Map
只是一个接口。所以我的问题是:
使用 Map
接口创建 ImmutableMap
是否会被视为破坏 LSP,因为 Map
包含 put
和 putAll
方法?不实现 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
操作.如果将此层次结构与实际已经存在的接口层次结构和抽象 类(包括 AbstractMap
、SortedMap
、NavigableMap
、ConcurrentMap
、ConcurrentNavigableMap
...) 你会一团糟。
所以没有完美的答案,但在我看来最好的解决方案是让 ImmutableMap
实现 Map
并确保你编写的每个方法都带有 Map
作为一个参数清楚地记录了 Map
必须具有的任何属性,以及如果传递了错误类型的 Map
则抛出的异常。