聚合(aggregation)表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不一定是A对象的一部分。例如大雁是群居动物,所以每只大雁都是属于一个雁群,一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。
合成(composition)则是一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期是相同的。大雁和翅膀就是整体和部分的关系,并且他们的生命周期是相同的,所以就是合成关系。
对象的集成关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现是与它的父类有这非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当我们需要复用子类是,如果继承下来的实现不适合解决新的问题,则父类必须重新写或者被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。
所以我们应该尽量使用合成/聚合,尽量不要使用类的继承。---合成/聚合复用原则。优先使用对象的合成/聚合将有助于我们保持每个类被封装,并集中在单个任务上,这样类和类继承层次会保持较小规模,并且不大可能增长为不可控制的庞然大物。
桥接模式(Bridge):将抽象部分和它的实现部分分离,使它们都可以独立的变化。
什么叫抽象和它的实现分离,这并不是说,让抽象类和其派生类分离,因为这没有任何意义。实现是指的是抽象类和它的派生类用来实现自己的对象。就下文来说,就是让手机既可以按照品牌来分类,也可以按照功能来分类。
#ifndef BRIDGE_H #define BRIDGE_H #include <iostream> #include <string> using namespace std; class HandsetSoft { public: virtual void Run()=0; }; class HandsetGame :public HandsetSoft { public: void Run() { cout << "运行手机游戏。\n"; } }; class HandsetAddressList:public HandsetSoft { public: void Run() { cout << "运行手机通讯录。\n"; } }; class HandsetBrand { protected: HandsetSoft * soft; public: HandsetBrand(){} void SetHandsetSoft(HandsetSoft * se){ soft = se; } virtual void Run()=0; }; class HandsetBandN :public HandsetBrand { public: void Run() { cout << "手机品牌Nokia:\n"; soft->Run(); } }; class HandsetBandS :public HandsetBrand { public: void Run() { cout << "手机品牌Samsung:\n"; soft->Run(); } }; #endif
#include "Bridge.h" int main() { HandsetBrand * Nokia = new HandsetBandN; Nokia->SetHandsetSoft(new HandsetGame); Nokia->Run(); Nokia->SetHandsetSoft(new HandsetAddressList); Nokia->Run(); HandsetBrand * Samsung = new HandsetBandS; Samsung->SetHandsetSoft(new HandsetGame); Samsung->Run(); Samsung->SetHandsetSoft(new HandsetAddressList); Samsung->Run(); return 0; }
时间: 2024-10-24 21:05:13