组合模式(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
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);}}
}
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();}
}
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);}}
}
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}";}}
}
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
<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
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";}}
}