设计模式C++组合

设计模式C++组合

注:参考视频:【设计模式(完整版)】2.3组合_哔哩哔哩_bilibili

分类:(对象)结构型

树形结构.可以当做数据结构中的森林看待.

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

1.组件(Component)接口描述了树中简单项目和复杂项目所共有的操作.

2.叶节点(leaf)是树的基本结构,它不包含子项目.

3.容器(Container)--又名"组合(Composite)"--是包含叶节点或其他容器等子项目的单位.

4.客户端(Client)通过组件接口与所有项目交互.

举个例子:如下图,记事本中查看中有一个菜单状态栏和子菜单缩放,子菜单缩放中有放大缩小恢复默认缩放.

共同的execute()都是鼠标焦点置于上面.leaf就是各个功能,而Composite就是缩放.

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

另一个例子:借助组合模式在图形编辑器中实现一系列的几何图形

既可以空白画布上可以画圆,亦可以在已经有复杂图案上的画布上添加一个圆.都依赖画布这个接口.

优点:

可以利用多态和递归机制更方便地使用复杂树结构,

开闭原则:无需更改现有代码,就可以在应用中添加新元素,使其成为对象树的一部分.

缺点:

对于功能差异较大的类,提供公共接口或许会有困难,在特定情况下,需要过度一般化组件接口,使其变得令人难以理解.(不要硬套组合这个设计模式)

代码:

#include <iostream>
#include <list>
#include <string>
//接口:不管是商品还是盒子,都依赖这个接口
class OrderNode
{
protected:
    OrderNode* m_parent;
    float m_price;
public:
    virtual ~OrderNode() {}
    virtual bool isComposite() const
    {
        return false;
    }
    virtual std::string operation() = 0;
    //ADD,Remove不放到接口里,保持和类图一致
​
    OrderNode() :m_parent(nullptr), m_price(0.0f)
    {
​
    }
    OrderNode(OrderNode* m_parent,float price) :m_parent(m_parent), m_price(price)
    {
​
    }
    void setParent(OrderNode* node)
    {
        m_parent = node;
    }
    OrderNode* getParent()
    {
        return m_parent;
    }
    void setPrice(float price)
    {
        m_price = price;
    }
    float getPrice()
    {
        return m_price;
    }
};
//产品
class Product :public OrderNode
{
public:
    ~Product() {}
    Product(float price) :OrderNode(nullptr,price) {}
    virtual std::string operation()override
    {
        return "产品";
    }
};
//盒子
class Box :public OrderNode
{
protected:
    std::list<OrderNode*> m_children;
public:
    ~Box() {}
    Box() {}
    bool isComposite() const 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;
        //c即可能是盒子也可能是产品,是盒子就递归
        for (auto c : m_children)
        {
            if (c == m_children.back())
            {
                result += c->operation();
            }
            else
            {
                result += c->operation() + '+';
            }
            m_price += c->getPrice();
        }
        return "盒子("+result+")";
    }
};
void clientCode(OrderNode* node)
{
    std::cout << "结构:" << node->operation() << std::endl;
    std::cout << "价格:" << node->getPrice() << std::endl;
}
​
int main()
{
    std::cout << "#处理叶子节点....." << std::endl;
    Product leaf(5.0f);
    clientCode(&leaf);
​
    std::cout << "\n\n";
    std::cout << "#处理组合节点..." << std::endl;
    Box tree;
    Box branch1;
    Box branch2;
    Product leaf1(5.0f);
    Product leaf2(5.0f);
    Product leaf3(5.0f);
    tree.Add(&branch1);
    tree.Add(&branch2);
    branch1.Add(&leaf1);
    branch1.Add(&leaf2);
    branch2.Add(&leaf3);
    clientCode(&tree);
    std::cout << "\n\n";
    tree.Add(&leaf);
    clientCode(&tree);
​
}
​

  • 25
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值