组合模式-C#实现

组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。

组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

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

主要解决:它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,

从而使得客户程序与复杂元素的内部结构解耦。

何时使用: 1、您想表示对象的部分-整体层次结构(树形结构)。

2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

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

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

应用实例: 1、算术表达式包括操作数、操作符和另一个操作数,其中,另一个操作数也可以是操作数、操作符和另一个操作数。

2、在 JAVA AWT 和 SWING 中,对于 Button 和 Checkbox 是树叶,Container 是树枝。

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

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

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

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

组合模式中涉及到三个角色:

抽象构件(Component)角色:这是一个抽象角色,上面实现中Graphics充当这个角色,

它给参加组合的对象定义出了公共的接口及默认行为,可以用来管理所有的子对象(在透明式的组合模式是这样的)。

在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝结构对象给出。

树叶构件(Leaf)角色:树叶对象时没有下级子对象的对象,上面实现中Line和Circle充当这个角色,定义出参加组合的原始对象的行为

树枝构件(Composite)角色:代表参加组合的有下级子对象的对象,

上面实现中ComplexGraphics充当这个角色,树枝对象给出所有管理子对象的方法实现,如Add、Remove等。

该实例基于WPF实现,直接上代码,下面为三层架构的代码。

一 Model

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Shapes;

namespace 设计模式练习.Model.组合模式
{
    //画一个圆
    internal class Circle : Graphics
    {
        List<Graphics> graphics = new List<Graphics>();
        public Circle(string name) : base(name)
        {
        }

        //开始绘制
        public override void Draw()
        {
            //绘制图形
            foreach (var line in graphics)
            {
                line.Draw();
                this.Description += $"{line.Name}";
            }
        }

        public void Add(Graphics line)
        {
            graphics.Add(line);
        }

        public void Remove(Graphics line)
        {
            graphics.Remove(line);
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 设计模式练习.Model.组合模式
{
    //图形抽象类
    public abstract class Graphics
    {
        public string Name { get; set; }
        public string Description { get; set; }

        protected Graphics(string name)
        {
            Name = name;
        }

        //画图方法
        public abstract void Draw();
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 设计模式练习.Model.组合模式
{
    public class Line : Graphics
    {
        //存储多个图形
        private List<Graphics> points = new List<Graphics>();

        //复杂图形类
        public Line(string name) : base(name)
        {
        }

        //画图: 由多个点组成的线段
        public override void Draw()
        {
            foreach (Graphics point in points)
            {
                point.Draw();
                this.Description += $"画{point.Name},";
            }

        }


        public void Add(Graphics point)
        {
            points.Add(point);
        }

        public void Remove(Graphics point)
        {
            points.Remove(point);
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 设计模式练习.Model.组合模式
{
    //简单图形:点
    public class Point : Graphics
    {
        public Point(string name) : base(name)
        {
        }

        //重写父类抽象方法
        public override void Draw()
        {
            this.Description = $"画{Name}";
        }
    }
}
cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Animation;

namespace 设计模式练习.Model.组合模式
{
    //绘制复杂图形
    public class Rectangle : Graphics
    {
        //记录加入的线段
        List<Graphics> lines = new List<Graphics>();

        public Rectangle(string name) : base(name)
        {
        }

        //开始绘制
        public override void Draw()
        {
            //绘制图形
            foreach (var line in lines)
            {
                line.Draw();
                this.Description += $"{line.Name}";
            }
        }

        public void Add(Graphics line)
        {
            lines.Add(line);
        }

        public void Remove(Graphics line)
        {
            lines.Remove(line);
        }
    }
}

二 View

XML 复制代码
<Window x:Class="设计模式练习.View.组合模式.Combination"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:设计模式练习.View.组合模式"
        mc:Ignorable="d"
        Title="Combination" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Content="{Binding Res1}"/>
        <Label Grid.Row="1" Grid.Column="0" Content="{Binding Res2}"/>
        <Label Grid.Row="2" Grid.Column="0" Content="{Binding Res3}"/>
        <Label Grid.Row="3" Grid.Column="0" Content="{Binding Res4}"/>

        <Button Grid.Row="0" Grid.Column="2" Content="画点" Command="{Binding add1Command}"/>
        <Button Grid.Row="1" Grid.Column="2" Content="画线" Command="{Binding add2Command}"/>
        <Button Grid.Row="2" Grid.Column="2" Content="画矩形" Command="{Binding add3Command}"/>
        <Button Grid.Row="3" Grid.Column="2" Content="画圆" Command="{Binding Add4Command}"/>

        <Label Grid.Row="0" Grid.Column="1" Visibility="{Binding A1}">
            <Label.Content>
                <TextBlock Text="." FontSize="100" VerticalAlignment="Center"/>
            </Label.Content>
        </Label>
        <Label Grid.Row="1" Grid.Column="1" Visibility="{Binding A2}" >
            <Label.Content>
                <Line X1="10" Y1="20" X2="260" Y2="20" Stroke="Red" StrokeThickness="10"/>
            </Label.Content>
        </Label>
        <Rectangle Grid.Row="2" Grid.Column="1" Fill="Red" Width="100" Height="100" StrokeThickness="3" Visibility="{Binding A3}"/>
        <Ellipse Grid.Row="3" Grid.Column="1" Width="100" Height="100" Fill="Blue" Visibility="{Binding A4}"/>
    </Grid>
</Window>

三 ViewModel

cs 复制代码
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 设计模式练习.Model.组合模式;

namespace 设计模式练习.ViewModel.组合模式
{
    partial class Combination_ViewModel : ObservableObject
    {


        [ObservableProperty]
        private string res1;

        [ObservableProperty]
        private string res2;

        [ObservableProperty]
        private string res3;

        [ObservableProperty]
        private string res4;

        [ObservableProperty]
        private string a1;

        [ObservableProperty]
        private string a2;

        [ObservableProperty]
        private string a3;

        [ObservableProperty]
        private string a4;

        public Combination_ViewModel()
        {
            A1 = "Collapsed";
            A2 = "Collapsed";
            A3 = "Collapsed";
            A4 = "Collapsed";
        }

        //画点
        [RelayCommand]
        private void add1()
        {
            Graphics point = new Point("点1");
            point.Draw();
            Res1 = point.Description;

            A1 = "Visible";
        }

        //画线
        [RelayCommand]
        private void add2()
        {
            Graphics point = new Point("点1");
            Graphics point2 = new Point("点2");
            Graphics point3 = new Point("点3");

            Line line = new Line("线");
            line.Add(point);
            line.Add(point2);
            line.Add(point3);

            line.Draw();
            Res2 = line.Description;

            A2 = "Visible";
        }

        //画矩形
        [RelayCommand]
        private void add3()
        {

            Line line = new Line("线");
            Line line2 = new Line("线2");
            Line line3 = new Line("线3");

            Rectangle rectangle = new Rectangle("矩形");
            rectangle.Add(line);
            rectangle.Add(line2);
            rectangle.Add(line3);

            rectangle.Draw();
            Res3 = rectangle.Description;

            A3 = "Visible";
        }

        //画圆
        [RelayCommand]
        private void Add4()
        {

            Rectangle rectangle = new Rectangle("矩形");
            Rectangle rectangle2 = new Rectangle("矩形2");

            Circle circle = new Circle("圆");
            circle.Add(rectangle);
            circle.Add(rectangle2);

            circle.Draw();
            Res4 = circle.Description;

            A4 = "Visible";
        }
    }
}
相关推荐
△曉風殘月〆6 小时前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
逐·風8 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
m0_6569747411 小时前
C#中的集合类及其使用
开发语言·c#
九鼎科技-Leo11 小时前
了解 .NET 运行时与 .NET 框架:基础概念与相互关系
windows·c#·.net
九鼎科技-Leo14 小时前
什么是 ASP.NET Core?与 ASP.NET MVC 有什么区别?
windows·后端·c#·asp.net·mvc·.net
.net开发14 小时前
WPF怎么通过RestSharp向后端发请求
前端·c#·.net·wpf
小乖兽技术14 小时前
C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)
c++·c#·交互·ipc
幼儿园园霸柒柒15 小时前
第七章: 7.3求一个3*3的整型矩阵对角线元素之和
c语言·c++·算法·矩阵·c#·1024程序员节
平凡シンプル17 小时前
C# EF 使用
c#
丁德双17 小时前
winform 加载 office excel 插入QRCode图片如何设定位置
c#·excel