组合模式

 

组合模式

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

这种模式创建了一个包含自己对象组的类。该类提供了修改相同对象组的方式。

我们通过下面的实例来演示组合模式的用法。实例演示了一个组织中员工的层次结构。

介绍

意图:将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以向处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。 2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

如何解决:树枝和叶子实现统一接口,树枝内部组合该接口。

关键代码:树枝内部组合该接口,并且含有内部属性 List,里面放 Component。

应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作符也可以是操作数、操作符和另一个操作数。 2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。

优点: 1、高层模块调用简单。 2、节点自由增加。

缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。

注意事项:定义时为具体类。

 

 

例子:

组合模式:  和树差不多

 DMComposite 类里不够完善,比如取孩子和 移除孩子,添加孩子,在操作之前 都需要 做一些提前处理,空处理之类的。

Window 操作系统 里面的文件目录 就是用树(组合模式)实现的。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class dm06Composite : MonoBehaviour {

	// Use this for initialization
	void Start ()
    {
        DMComposite root = new DMComposite("Root");

        DMLeaf leaf1 = new DMLeaf("GameObject");

        DMLeaf leaf2 = new DMLeaf("GameObject (2)");

        DMComposite gameObject1 = new DMComposite("GameObject (1)");

        root.Add(leaf1);
        root.Add(gameObject1);
        root.Add(leaf2);

        DMLeaf child1 = new DMLeaf("GameObject");
        DMLeaf child2 = new DMLeaf("GameObject (1)");
        gameObject1.Add(child1);
        gameObject1.Add(child2);

        ReadComponent(root);
    }
	

	// Update is called once per frame
	void Update () {
		
	}

    //深度
    private void ReadComponent(DMComponent component)
    {
        Debug.Log(component.Name);
        List<DMComponent> childrens = component.children;

        if (childrens==null||childrens.Count==0)
        {
            //叶子
            return;
        }
        foreach (DMComponent child in childrens)
        {
            ReadComponent(child);
        }
    }
}



public abstract class DMComponent
{
    protected string mName;
    public string Name { get { return mName; } }

    public DMComponent(string name)
    {
        mName = name;
        mChildren = new List<DMComponent>();
    }
    public List<DMComponent> children{ get { return mChildren; }}
    protected List<DMComponent> mChildren;
    public abstract void Add(DMComponent Dmc);
    public abstract void RemoveChild(DMComponent c);
    public abstract DMComponent GetChild(int index);
}
public class DMLeaf : DMComponent
{
    public DMLeaf(string name) : base(name)
    {
    }

    public override void Add(DMComponent Dmc)
    {
        return;
    }

    public override DMComponent GetChild(int index)
    {
        return null;
    }

    public override void RemoveChild(DMComponent c)
    {
        return;
    }
}
public class DMComposite : DMComponent
{
    public DMComposite(string name) : base(name)
    {
    }

    public override void Add(DMComponent Dmc)
    {
        mChildren.Add(Dmc);
    }

    public override DMComponent GetChild(int index)
    {
        

        return mChildren[index];
    }

    public override void RemoveChild(DMComponent c)
    {
        mChildren.Remove(c);
     }
}

 

 

二叉树的链式储存,说白了就是靠引用来储存,不过因为是二叉树 因此有它的存储规律。和一些公式之类的,一般很少用,

每个子节点都有它的父节点。通过引用来表示相互间的关系,责任链模式主要也是通过引用来表示引用关系。  很类似。

namespace 二叉树链式存储
{
    class BSNode
    {
        public BSNode LeftChild { get; set; } = null;

        public BSNode RightChild { get; set; } = null;

        public BSNode Parent { get; set; } = null;

        public int dada { get; set; }

        public BSNode() { }
        public BSNode(int item)
        {
            this.dada = item;
        }
    }

class BSTree
    {
        private BSNode Root = null;


        /// <summary>
        /// 大于 根结点 放在右边 小于放在左边
        /// </summary>
        /// <param name="item"></param>
        public void Add(int item)
        {
            BSNode newBSNode = new BSNode(item);

            if (Root == null)
            {
                Root = newBSNode;
            }
            else
            {
                BSNode temp = Root;
                while (true)
                {               //如果  比当前 结点的数据大就放右边    小于就 放左边
                    if (item >= temp.dada)
                    {
                        // 如果右边为空了就插入 节点
                        if (temp.RightChild == null)
                        {
                            temp.RightChild = newBSNode;
                            newBSNode.Parent = temp;
                            break; //插入了数据 跳出循环
                        }
                        else
                        {
                            temp = temp.RightChild;
                        }
                    }
                    else  //小于 放在左边
                    {
                        //往左边插入
                        if (temp.LeftChild == null)
                        {
                            temp.LeftChild = newBSNode;
                            newBSNode.Parent = temp;
                            break; //插入了数据  跳出循环
                        }
                        else //继续执行
                        {
                            temp = temp.LeftChild;

                        }
                    }
                }

            }

        }

        public void MiddleTraverSal() { MiddleTraverSal(Root); }

        private void MiddleTraverSal(BSNode node)
        {
            if (node == null)
            {
                return;
            }

            MiddleTraverSal(node.LeftChild);
            Console.Write(node.dada + " ");
            MiddleTraverSal(node.RightChild);

        }

        public bool Find(int item)
        {
            return Find(item, Root);
        }
        private bool Find(int item, BSNode node)
        {
            if (node == null)
            {
                return false;
            }

            if (node.dada == item)
            {
                return true;
            }
            else
            {
                if (node.dada <= item)
                {
                    return Find(item, node.RightChild);
                }
                else
                {
                    return Find(item, node.LeftChild);

                }


            }

            return false;
        }

        public bool Delete(int item)
        {
            BSNode temp = Root;

            while (true)
            {
                if (temp == null) return false;
                if (temp.dada == item)
                {
                    Delete(temp);
                    return true;
                }
                if (item > temp.dada)
                {
                    temp = temp.RightChild;
                }
                else
                {
                    temp = temp.LeftChild;
                }
            }
        }
        public void Delete(BSNode node)
        {
            ///删除的是  叶子 结点  情况1
            if (node.LeftChild == null && node.RightChild == null)
            {
                if (node.Parent == null) //无 父 结点 就是 根结点
                {
                    Root = null;
                }
                else if (node.Parent.RightChild == node) //如果结点是 父节点的 右结点 
                {
                    node.Parent.RightChild = null;
                }
                else if (node.Parent.LeftChild == node)
                {
                    node.Parent.LeftChild = null;
                }

                return;
            }

            //只有右孩子  情况2
            if (node.LeftChild == null && node.RightChild != null)
            {
                node.dada = node.RightChild.dada; //拿到数据 拿到引用
                node = node.RightChild; //左 节点已经为null 直接拿到引用
                return;
            }

            if (node.LeftChild != null && node.RightChild == null)
            {
                node.dada = node.LeftChild.dada;
                node = node.LeftChild;
                return;
            }

            // 情况3  左右孩子都有


            BSNode Temp = node.RightChild;
            while (true) //左结点最小 的
            {
                if (Temp.LeftChild != null) //存在左结点  一直查找到最后  右结点 中 的左子节点中寻找最小的 。  
                {
                    Temp = Temp.LeftChild;
                }
                else
                {
                    break;
                }
            }
            //BSNode Temp = node.LeftChild;
            //while (true)
            //{
            //    if (Temp.RightChild!=null)
            //    {
            //        Temp = Temp.RightChild;
            //    }
            //    else
            //    {
            //        break;
            //    }
            //}
            node.dada = Temp.dada;
            Delete(Temp);

        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            BSTree bSTree = new BSTree();
            int[] data = { 62, 58, 88, 47, 73, 99, 35, 51, 93, 37 };

            foreach (int item in data)
            {
                bSTree.Add(item);
            }
            bSTree.Delete(88);
            bSTree.MiddleTraverSal();
            Console.WriteLine(bSTree.Find(99));
            Console.WriteLine(bSTree.Find(990));
        }
    }
}

 

组合模式:资料 https://www.cnblogs.com/lfxiao/p/6816026.html文件 杀毒例子 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值