特性:
组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
意图
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得用户对单个对象和组合对象的使用具有一致性。
优点:
定义了包含基本对象和组合对象的类层次结构
在组合模式中,基本对象可以被组合成更复杂的组合对象,而组合对象又可以组合成更复杂的组合对象,可以不断地递归组合下去,从而构成一个统一的组合对象的类层次结构
统一了组合对象和叶子对象
在组合模式中,可以把叶子对象当作特殊的组合对象看待,为它们定义统一的父类,从而把组合对象和叶子对象的行为统一起来
简化了客户端调用
组合模式通过统一组合对象和叶子对象,使得客户端在使用它们的时候,就不需要再去区分它们,客户不关心使用的到底是什么类型的对象,这就大大简化了客户端的使用
更容易扩展
由于客户端是统一的面对Component来操作,因此,新定义的Composite或Leaf子类能够很容易的与已有的结构一起工作,而客户端不需要为增添了新的组件类而改变
缺点:
很难限制组合中的组件类型
容易增加新的组件也会带来一些问题,比如很难限制组合中的组件类型。这在需要检测组件类型的时候,使得我们不能依靠编译期的类型约束来完成,必须在运行期间动态检测。
适用性
以下情况下适用Composite模式:
1.你想表示对象的部分-整体层次结构
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
例子:
一个机器生产厂商,下面有一个统一管理的部件(composite),用来管理每个独立的机器(concreteMachine),以进行正常运转。管理部件中只需要正确的管理自身所管理的机器运行即可,而不用关心具体是什么机器在运转。
类图:
实现代码:
machine.h
#ifndef MACHINE_H #define MACHINE_H class Machine { public: Machine(void); ~Machine(void); virtual void start(){}; virtual void run(){}; virtual void stop(){}; protected: virtual bool addMachine(Machine* mac); virtual bool removeMachine(Machine* mac); virtual Machine* getMachine(int index); }; #endif
machine.cpp
#include "StdAfx.h" #include "machine.h" Machine::Machine(void) { } Machine::~Machine(void) { } bool Machine::addMachine( Machine* mac ) { return false; } bool Machine::removeMachine( Machine* mac ) { return false; } Machine* Machine::getMachine( int index ) { return NULL; }
machinecomposite.h
#ifndef CMACHINECOMPOSITE_H #define CMACHINECOMPOSITE_H #include "machine.h" #include <vector> class CMachineComposite : public Machine { public: CMachineComposite(void); ~CMachineComposite(void); bool addMachine(Machine* mac); bool removeMachine(Machine* mac); Machine* getMachine(int index); private: std::vector<Machine*> m_machineList; }; #endif
machinecomposite.cpp
#include "StdAfx.h" #include "machineComposite.h" #include <algorithm> CMachineComposite::CMachineComposite(void) { } CMachineComposite::~CMachineComposite(void) { } bool CMachineComposite::addMachine( Machine* mac ) { m_machineList.push_back(mac); return true; } bool CMachineComposite::removeMachine( Machine* mac ) { std::vector<Machine*>::iterator it; it = find(m_machineList.begin(),m_machineList.end(),mac); if (m_machineList.end() != it) { m_machineList.erase(it); return true; } return false; } Machine* CMachineComposite::getMachine( int index ) { return m_machineList[index]; }
abstractmachine.h
#ifndef CABSTRACTMACHINE_H #define CABSTRACTMACHINE_H #include "machine.h" class CAbstractMachine : public Machine { public: CAbstractMachine(void); ~CAbstractMachine(void); void start(); void run(); void stop(); }; #endif
abstractmachine.cpp
#include "StdAfx.h" #include "abstractMachine.h" CAbstractMachine::CAbstractMachine(void) { } CAbstractMachine::~CAbstractMachine(void) { } void CAbstractMachine::start() { } void CAbstractMachine::run() { } void CAbstractMachine::stop() { }
concretemachine.h
#ifndef CONCRETEMACHINE_H #define CONCRETEMACHINE_H #include "abstractMachine.h" #include <iostream> class ConcreteMachine : public CAbstractMachine { public: ConcreteMachine(void); ~ConcreteMachine(void); void start(); void run(); void stop(); }; #endif
concretemachine.cpp
#include "StdAfx.h" #include "concreteMachine.h" ConcreteMachine::ConcreteMachine(void) { } ConcreteMachine::~ConcreteMachine(void) { } void ConcreteMachine::start() { std::cout<<"Machine 1 have start."<<std::endl; } void ConcreteMachine::run() { std::cout<<"Machine 1 have run."<<std::endl; } void ConcreteMachine::stop() { std::cout<<"Machine 1 have stop."<<std::endl; }
concretemachine2.h
#ifndef CONCRETEMACHINE_HH #define CONCRETEMACHINE_HH #include "abstractMachine.h" #include <iostream> class ConcreteMachine2 : public CAbstractMachine { public: ConcreteMachine2(void); ~ConcreteMachine2(void); void start(); void run(); void stop(); }; #endif
concretemachine2.cpp
#include "StdAfx.h" #include "concreteMachine2.h" ConcreteMachine2::ConcreteMachine2(void) { } ConcreteMachine2::~ConcreteMachine2(void) { } void ConcreteMachine2::start() { std::cout<<"Machine 2 have start."<<std::endl; } void ConcreteMachine2::run() { std::cout<<"Machine 2 have run."<<std::endl; } void ConcreteMachine2::stop() { std::cout<<"Machine 2 have stop."<<std::endl; }
演示代码:
// Composite.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "stdlib.h" #include "machineComposite.h" #include "concreteMachine.h" #include "concreteMachine2.h" int _tmain(int argc, _TCHAR* argv[]) { ConcreteMachine* mc1 = new ConcreteMachine(); ConcreteMachine2* mc2 = new ConcreteMachine2(); CMachineComposite* mc = new CMachineComposite(); mc->addMachine(mc1); mc->addMachine(mc2); mc->getMachine(1)->start(); mc->getMachine(1)->run(); mc->getMachine(1)->stop(); mc->getMachine(0)->start(); mc->getMachine(0)->run(); mc->getMachine(0)->stop(); mc->removeMachine(mc1); delete mc1; delete mc2; delete mc; system("pause"); return 0; }