面向对象的一些法则

    技术2022-05-11  154

    面向对象的一些法则:法则1:优先使用(对象)组合,而非继承组合是一种通过创建一个组合了其它对象的对象,从而获得新功能的复用方 法有些时候也称之为“聚合”(aggregation)或“包容”containment)聚合:一个对象拥有另一个对象或对另一个对象负责(即一个对象包含另一个对象或是另一个对象的一部分),并且聚合对象和其所有者具有相同的生命周期。包容:一种特殊类型的组合,对于其它对象而言,容器中的被包含对象是不可见的,其它对象仅能通过容器对象来访问被包含对象。(Coad)

    组合的优点和缺点:优点:1、容器类仅能通过被包含对象的接口来对其进行访问。2、“黑盒”复用,因为被包含对象的内部细节对外是不可见,封装性好。3、实现上的相互依赖性比较小。(被包含对象与容器对象之间的依赖关系比较少)4、每一个类只专注于一项任务。5、通过获取指向其它的具有相同类型的对象引用,可以在运行期间动态地定义(对象的)组合。缺点:1、从而导致系统中的对象过多。2、为了能将多个不同的对象作为组合块(composition block)来使用,必须仔细地对接口进行定义。

    继承的优点和缺点优点:1、容易进行新的实现,因为其大多数可继承而来。2、易于修改或扩展那些被复用的实现。缺点:1、破坏了封装性,因为这会将父类的实现细节暴露给子类。2、“白盒”复用,因为父类的内部细节对于子类而言通常是可见的。3、当父类的实现更改时,子类也不得不会随之更改。4、从父类继承来的实现将不能在运行期间进行改变。

    法则2:针对接口编程,而非(接口的)实现

    接口接口是一个对象在对其它的对象进行调用时所知道的方法集合。一个对象可以有多个接口(实际上,接口是对象所有方法的一个子集)类型是对象的一个特定的接口。不同的对象可以具有相同的类型,而且一个对象可以具有多个不同的类型。一个对象仅能通过其接口才会被其它对象所了解。接口是实现插件化(pluggability)的关键实现继承和接口继承实现继承( 类继承):一个对象的实现是根据另一个对象的实现来定义的。接口继承( 子类型化):描述了一个对象可在什么时候被用来替代另一个对象。C++的继承机制既指类继承,又指接口继承。C++通过继承纯虚类来实现接口继承。

    优点:Client不必知道其使用对象的具体所属类。一个对象可以很容易地被(实现了相同接口的)的另一个对象所替换。对象间的连接不必硬绑定(hardwire)到一个具体类的对象上,因此增加了灵活性。松散藕合(loosens coupling)。增加了重用的可能性。提高了(对象)组合的机率,因为被包含对象可以是任何实现了一个指定接口的类。缺点:设计的复杂性略有增加

    法则3:开放-封闭法则(OCP)开放-封闭法则认为我们应该试图去设计出永远也不需要改变的模块我们可以添加新代码来扩展系统的行为。我们不能对已有的代码进行修改符合OCP的模块需满足两个标准:可扩展,即“对扩展是开放的”(Open For Extension)-模块的行为可以被扩展,以需要满足新的需求。不可更改,即“对更改是封闭的”(Closed for Modification)-模块的源代码是不允许进行改动的

    法则4:Liskov替换法则(LSP)Liskov替换法则(LSP)是根据“多态”而得出的,在PageManager 中有很多地方使用到这中作法:例如:   Public void drawAno(CUAo * pUao){        pUao->Draw(dc);}方法drawAno应该可与CUAo类的任何子类一起工作,若一个函数未能满足LSP,那么可能是因为它显式地引用了超类的一些或所有子类。这样的函数也违背了OCP,因为当我们创建一个新的子类时,会不得不进行代码的修改。为了保持LSP(并与开放-封闭法则一起),所有子类必须符合使用基类的client所期望的行为。

    LSP保证一个子类总是能够被用在其基类可以出现的地方

    来做个小小的测试:看看这样的关系应该怎样确定:长方形   正方形如果是你你应该怎样来设计他们之间的关系呢?

    class Rectangle  {public: virtual int area(); virtual void SetHeight(const int nHeight); virtual void SetWidth(const int nWidth); Rectangle(const int nHeight = 0,const int nWidth = 0); virtual ~Rectangle();protected: int m_nWidth; int m_nHeight;};class Square : public Rectangle{public: Square(const int nHeight = 0); virtual ~Square(); virtual void SetHeight(const int nHeight); virtual void SetWidth(const int nWidth);};

    从结果来讲我们违背了LSP法则一个数学意义上的正方形可能是一个四边形,但是一个Square对象不是一个Rectangle对象,因为一个Square对象的行为与一个Rectangle对象的行为是不一致的!从行为上来说,一个Square 不是一个Rectangle!一个Square对象与一个Rectangle对象之间不具有多态的特征。


    最新回复(0)