每当我遇到一个工厂将一个基于某种“低级”类型参数(如协议或外部资源的格式)的抽象基类实现返回给用户的情况时,我总是受到诱惑将抽象类转换为具有内部“策略工厂”的具体类,以便用户可以将实现类型传递给构造函数并直接使用基类。
我注意到.Net框架选择以这种方式实现Socket(而不是创建一个在构造时传递SocketType的DatagramSocket)。有哪些指导方针可以决定何时可以将层次结构扁平化为像这样的单个具体类?
答案 0 :(得分:3)
我认为重点是:“客户应该注意多少低级细节?”。
如果选择第一个解决方案(抽象基类),则会向客户端类隐藏更多详细信息。这样,客户端可以完全忽略低级别细节(协议,外部资源的格式)。当目标是完全隐藏实现细节和该实现中使用的类型时,我更喜欢这种方法。
否则,如果客户端已经知道低级实现的一些细节(例如客户端知道他将使用的套接字是UDP并且他也想知道那种信息),那么抽象基类方法可以是取而代之的是内部“战略工厂”。
答案 1 :(得分:2)
本着“喜欢构成而不是继承”的精神,我总是选择策略+工厂方法而不是继承。这给了我几个优点: *大多数情况下,每个策略都可以单独测试,而无需关心将使用它的类。 *同样,可以使用模拟策略测试客户端类 *策略可以设计成可组合的,例如使用装饰器模式,这可以提供很大的灵活性,而不会导致子类的爆炸。
总而言之,如果所有子细分的外部语义相同(应该如此),请遵循策略路线。