什么样的OOP原则(如果有的话)在动态类型的环境中与静态类型的环境(例如Ruby vs C#)相对应?这不是呼吁进行静态还是动态辩论,而是我想看看在这种划分的任何一方是否都存在接受的原则,它们适用于一个而不适用于另一方,或者适用于其他方面。在静态类型的OOP文献中,诸如“优先考虑组成而不是继承”这样的短语是众所周知的。它们在动态方面是否同样适用?
例如,在动态类型的环境中,似乎耦合的粒度不超过方法的级别。换句话说,任何给定的函数调用只会将调用者耦合到该特定接口(interface),任何类都可能满足-换句话说,就是像该特定鸭子那样发出嘎嘎声的任何东西。
另一方面,在Java中,耦合的粒度可以和包一样高。特定的方法调用不仅会与另一个类/接口(interface)建立契约,而且还会将其耦合到该类/接口(interface)的package/jar/assembly中。
这样的差异会引起不同的原理和模式吗?如果是这样,这些差异是否已明确表达? Ruby Pickaxe书中有一个部分朝这个方向发展(鸭打字/类不是类型),但是我想知道是否还有其他内容。我知道Design Patterns in Ruby,但尚未阅读。
编辑-有人争辩说Liskov在动态环境中的应用与在静态环境中的应用不同,但是我不禁认为它确实适用。一方面,没有与整个类(class)的高层契约(Contract)。但是,不是所有对任何给定类的调用都构成了隐式契约,子类需要像Liskov所规定的那样满足隐式契约吗?考虑以下。 “做一些吧东西”中的调用创建了一个契约(Contract),子类需要遵守该契约(Contract)。这不是“像对待基类一样处理专用对象”的情况吗?
class Bartender
def initialize(bar)
@bar = bar
end
def do_some_bar_stuff
@bar.open
@bar.tend
@bar.close
end
end
class Bar
def open
# open the doors, turn on the lights
end
def tend
# tend the bar
end
def close
#clean the bathrooms
end
end
class BoringSportsBar < Bar
def open
# turn on Golden Tee, fire up the plasma screen
end
def tend
# serve lots of Bud Light
end
end
class NotQuiteAsBoringSportsBar < BoringSportsBar
def open
# turn on vintage arcade games
end
end
class SnootyBeerSnobBar < Bar
def open
# replace empty kegs of expensive Belgians
end
def tend
# serve lots of obscure ales, porters and IPAs from 124 different taps
end
end
# monday night
bartender = Bartender.new(BoringSportsBar.new)
bartender.do_some_bar_stuff
# wednesday night
bartender = Bartender.new(SnootyBeerSnobBar.new)
bartender.do_some_bar_stuff
# friday night
bartender = Bartender.new(NotQuiteAsBoringSportsBar.new)
bartender.do_some_bar_stuff
最佳答案
我认为您要触及的本质区别是:
组1中的语言趋向于具有动态类型并且不支持编译时检查的接口(interface),组2中的语言趋向于具有静态类型并支持编译时经过检查的接口(interface)。
我想说所有面向对象的原理都适用于这两种方法,但是
编辑
因此,为了回答您的原始问题,我检查了
http://c2.com/cgi/wiki?PrinciplesOfObjectOrientedDesign
和
http://www.dofactory.com/patterns/Patterns.aspx
在实践中,出于各种良好的原因(当然也有一些不好的理由),系统中并未遵循OO原则。充分的理由包括:性能方面的关注胜过纯设计质量的关注,替代结构/命名的文化 yield 超过纯设计质量的关注,以及以某种非特定语言的标准方式实现功能的额外工作的成本超过了纯语言的 yield 。一个纯净的设计。
诸如抽象工厂,构建器,工厂方法,原型(prototype),适配器,策略,命令链,网桥,代理,观察者,访客甚至MVC/MMVM等较粗粒度的模式在小型系统中往往较少使用,因为有关代码较少,因此创建此类结构的好处不是很大。
在第1组代码中,更细粒度的模式(例如状态,命令,工厂方法,复合,装饰器,外观,Flyweight,内存,模板方法)可能更常见,但通常有几种设计模式不适用于这样的对象,而不适用于对象的不同部分一个对象,而在第2组中,代码模式倾向于以每个对象一个模式为基础。
恕我直言,在大多数第1组语言中,将所有全局数据和功能视为一种单例“应用程序”对象是很有意义的。我知道我们将要模糊过程和OO编程之间的界线,但是在很多情况下,这种代码肯定像“Application”对象一样嘎嘎作响! :)
诸如Iterator之类的一些非常细粒度的设计模式倾向于内置到第1组语言中。
关于design-patterns - OOP和动态键入(不是静态还是动态),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1918310/