设计模式之组合设计模式

一、组合设计模式概念

组合模式 (Component) 是一种结构型设计模式,将对象组合成树形结构以表示“部分-整体”的层次结构。

组合模式使得用户对单个对象和组合对象的使用具有唯一性

 适用场景

  • 想要表示对象的部分-整体层次结构。
  • 想要客户端忽略组合对象与单个对象的差异,客户端将统一地使用组合结构中的所有对象。

组合设计模式的结构

  1. 组件 (Component) 接口描述了树中简单项目和复杂项目所共有的操作。
  2. 叶节点 (Leaf) 是树的基本结构, 它不包含子项目。一般情况下, 叶节点最终会完成大部分的实际工作, 因为它们无法将工作指派给其他部分。
  3. 容器 (Container)——又名 “组合 (Composite)”——是包含叶节点或其他容器等子项目的单位。 容器不知道其子项目所属的具体类, 它只通过通用的组件接口与其子项目交互。容器接收到请求后会将工作分配给自己的子项目, 处理中间结果, 然后将最终结果返回给客户端。
  4. 客户端 (Client) 通过组件接口与所有项目交互。 因此, 客户端能以相同方式与树状结构中的简单或复杂项目交互。

代码如下:

问题:复杂订单的计算,有两类对象:产品和盒子。一个盒子中可以包含多个产品或者多个小盒子这些盒子中可以再包含产品或者小盒子,以此类推。


解决方案:将对象组成树形结构以表示“部分-整体”的层次结构。使得用户对单个对象和组合对象的使用具有一致性。

#include <iostream>
#include <list>
#include <string>
//接口:不管是商品还是盒子,都依赖这个接口//为了实现树形结构
class OrderNode
{
protected:
	OrderNode* m_parent;
	float m_price;
public:
	virtual ~OrderNode() {}
	OrderNode() : m_parent(nullptr), m_price(0.0f) {}
	OrderNode(OrderNode* parent, float price) : m_parent(nullptr), m_price(price) {}

	void setParent(OrderNode* parent) { m_parent = parent; }
	OrderNode* getParent() { return m_parent; }
	virtual bool isComposite() { return false; }

	void setPrice(float price) { m_price = price; }
    float getPrice() { return m_price; }
    virtual std::string Operation() = 0;
};

class Product : public OrderNode
{
public:
	~Product() {}
    Product(float price):OrderNode(nullptr,price) {}
    std::string Operation() override{ return "Product"; }
};

class Box : public OrderNode
{
protected:
    std::list<OrderNode*> m_children;
public:
	~Box() {}
	Box() {}
    Box(OrderNode* parent,float price):OrderNode(parent, price) {}
	bool isComposite() override { return true; }
	void Add(OrderNode* node) 
	{
		m_children.push_back(node);
		node->setParent(this); 
		m_price += node->getPrice();
	}
	void Remove(OrderNode* node)
	{
        m_children.remove(node);//只是在容器中移除
        node->setParent(nullptr);
        m_price -= node->getPrice();

	}
   virtual std::string Operation() override
   { 
	   std::string result;
	   m_price = 0.0f;//重要
	   for (auto c : m_children)
	   {
		   if (c == m_children.back())
		   {
               result += c->Operation();
		   }
		   else
		   {
               result += c->Operation() + ",";
		   }
		   m_price += c->getPrice();
	   }
	   return "Box(" + result + ")";
   }
};

void clientCode(OrderNode* node)
{
	std::cout << "结构:" << node->Operation() << std::endl;
    std::cout << "价格:" << node->getPrice() << std::endl;
}
int main()
{
    /*Box* box1 = new Box(nullptr, 0.0f);
    Box* box2 = new Box(nullptr, 0.0f);
    Product* product1 = new Product(nullptr, 10.0f);
    Product* product2 = new Product(nullptr, 20.0f);
    Product* product3 = new Product(nullptr, 30.0f);
    Product* product4 = new Product(nullptr, 40.0f);
    box1->Add(product1);
    box1->Add(product2);
    box2->Add(product3);
    box2->Add(product4);
    box1->Add(box2);
    clientCode(box1);
    delete box1;
    delete box2;
    delete product1;
    delete product2;
    delete product3;
    delete product4;*/

	std::cout << "处理叶子节点:" << std::endl;
	Product leaf( 5.0f);
	clientCode(&leaf);

	std::cout << std::endl;
	std::cout << "处理组合节点:" << std::endl;
	Box tree;
	Box branch1;
    Box branch2;
	Product leaf_1(5.0f);
    Product leaf_2(10.0f);
    Product leaf_3(15.0f);
	tree.Add(&branch1);
    tree.Add(&branch2);
    branch1.Add(&leaf_1);
    branch1.Add(&leaf_2);
    branch2.Add(&leaf_3);
    clientCode(&tree);

    std::cout << std::endl;
	tree.Add(&leaf);
	clientCode(&tree);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值