• 设计模式【八】:组合模式


    设计模式【八】:组合模式

    伪代码

    伪代码引自Erich Gamma 等《Design Patterns》.

    class Equipment{
    public:
    	virtual ~Equipment();
    	const char* Name(){return _name;}
    	
    	virtual Watt Power();
    	virtual Currency NetPrice();
    	virtual Currency DiscountPrice();
    
    	virtual void Add(Equipment*);
    	virtual void Remove(Equipment*);
    	virtual Iterator<Equipment*>* CreateIterator();
    
    protected:
    	Equipment(const char*);
    private:
    	const char* _name;
    };
    
    class FloppyDisk: public Equiment{
    public:
    	FloppyDisk(const char*);
    	virtual ~FloppyDisk();
    	
    	virtual Watt Power();
    	virtual Currency NetPrice();
    	virtual Currency DiscountPrice();
    };
    
    class CompositeEquipment: public Equipment{
    public:
    	virtual ~CompositeEquipment();
    
    	virtual Watt Power();
    	virtual Currency NetPrice();
    	virtual Currency DiscountPrice();
    
    	virtual void Add(Equipment*);
    	virtual void Remove(Equipment*);
    	virtual Iterator<Equipment*>* CreateIterator();
    
    protected:
    	CompositeEquipment(const char*);
    private:
    	List<Equipment*> _equipment;
    };
    
    Currency CompositeEquipment::NetPrice(){
    	Iterator<Equipment*>* i = CreateIterator();
    	Currency total = 0;
    	
    	for(i->First();!i->IsDone();i->Next()){
    		total += i->CurrentItem->NetPrice();
    	}
    	delete i;
    	return total;
    }
    
    class Chassis:public CompositeEquipment{
    };
    
    class Cabinet:public CompositeEquipment{
    };
    //...
    
    Cabinet* cabinet = new Cabinet("PC Cabinet");
    Chassis* chassis = new Chassis("PC Chassis");
    cabinet->Add(chassis);
    
    Bus* bus = new Bus("Bus");
    bus->Add(new Card("16mb card"));
    
    chassis->Add(bus);
    chassis->Add(new FloppyDisk("3.5in disk"));
    
    cout<<"The total price is "<<chassis->NetPrice()<<endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    优缺点

    优点

    • 定义元对象和组合对象,并使对象可以递归地被组织起来。
    • 简化使用者的操作。使用者可以对组合对象和元对象一致对待。比如伪代码中计算总价格的函数在组合对象内部递归实现。
    • 易于添加组合对象的组件。

    缺点

    • 增大对组合对象的管理难度。因为在组合模式下对象的组件可以动态增删,所以不应依赖类名来判断组合对象的具体构成,确定对象具体构成需要在运行时动态检查。

    何时使用

    • 需要组织组合对象(往往是树形结构)。
    • 需要使用者忽略组合对象与元对象的区别。

    实现时技巧

    • 可构造子组件对父组件的隐式引用,比如在子组件的构造函数中添加一个指向父组件的指针。这样可以方便在对象树上的遍历。
    • 慎用共享的子组件。复用组件当然可以简化程序,但这会导致子组件可能有多个父组件。如果在子组件内维护一个指针链表可以管理这种情况,但这样反而使程序复杂。
    • 对象接口应当设计为各组件的并集。我们可以将叶子组件(元组件)视为不会返回子组件的一般组件,这样有助于简化接口设计。当然,这是灵活性与安全性的trade off,如果我们在叶子组件里声明全部的操作(包括对其子组件的操作,只不过返回null),其实是牺牲安全性来换取灵活性。
    • 可能需要对子组件排序。
    • 如果需要频繁遍历组件树,可缓存最近遍历的若干子组件等等。
    • 如果实现语言没有垃圾回收机制,需要考虑释放内存。一般父组件delete时需要delete它所有的子组件。
    • 总之,由于其树型组织结构,其注意事项有很多是与数据结构课上学的树有所对应。
  • 相关阅读:
    PHP笔记
    管理与系统思维
    联合主键NULL值过多,ON DUPLICATE KEY UPDATE不更新的问题
    LeetCode·1163.按字典序排在最后的子串·最小表示法
    【JavaScript】一文了解JS原型与原型链
    Kafka系列之:详细介绍部署Kafka Connect分布式集群
    软考高级系统架构设计师系列之:案例分析典型试题七
    Kotlin:协程基础
    为Arduino智能小车,做一款简易版的机智云APP
    【数据结构与算法】手撕二叉查找树
  • 原文地址:https://blog.csdn.net/swy_swy_swy/article/details/125509339