组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示"整体-部分"的层次关系
组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式
优点
高层模块调用简单
节点自由增加
缺点
组合模式的角色及职责:
Component:这是组合中对象声明接口,在适当情况下,实现所有类共有的接口默认行为,用于访问和管理 Component 子部件,Component 可以是抽象类或者接口
Composite:非叶子节点,用于存储子部件,在 Component 接口中实现子部件的相关操作,比如增加(add),删除等
Leaf:在组合中表示叶子节点,叶子节点没有子节点(它是被管理者)
这种模式使用的案例还是蛮多的,例如树形菜单的遍历、公司组织架构、文件和文件夹等等。下面就以公司的组织架构为例编写对应代码
客户端部分
program Combination;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
UnitCombination in 'UnitCombination.pas';
begin
try
//创建公司节点
var Component := TCompany.Create('软件开发公司');
//创建部门节点
var Department := TCompany.Create('财务部');
//将小组节点添加到部门节点
department.Add(TWorkers.Create('A 组'));
department.Add(TWorkers.Create('B 组'));
//将部门节点添加到公司节点下面
component.Add(department);
//和上面类似,只是又创建了一个部门
var Department01 := TCompany.Create('研发部');
Department01.Add(TWorkers.Create('A 组'));
Department01.Add(TWorkers.Create('B 组'));
//将部门节点添加到公司节点下面
component.Add(Department01);
//遍历节点(使用的是公司节点对象,所以会显示当前公司下所有的节点)
Component.Print;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
readln;
end.
核心代码
unit UnitCombination;
interface
uses
System.Generics.Collections;
type
//组织构成 => 对应 Component 角色
IOrganizationComponent = class abstract
procedure Print(); virtual; abstract;
procedure Add(OrganizationComponent: IOrganizationComponent); virtual; abstract;
procedure Remove(OrganizationComponent: IOrganizationComponent); virtual; abstract;
end;
//公司 => 对应 Composite 角色
TCompany = class(IOrganizationComponent)
private
FList: TList<IOrganizationComponent>;
FName: string;
public
procedure Add(OrganizationComponent: IOrganizationComponent); overload;
procedure Remove(OrganizationComponent: IOrganizationComponent); overload;
procedure Print(); override;
//带参构造
constructor Create(Name: string); overload;
end;
//员工 => 对应的是 Leaf 角色
TWorkers = class(IOrganizationComponent)
private
FName: string;
public
//带参构造
constructor Create(Name: string); overload;
procedure Print(); override;
end;
implementation
{ TComposite }
uses
System.SysUtils;
{ TCompany }
procedure TCompany.Add(OrganizationComponent: IOrganizationComponent);
begin
Self.FList.Add(OrganizationComponent);
end;
constructor TCompany.Create(Name: string);
begin
self.FName := Name;
Self.FList := TList<IOrganizationComponent>.create();
end;
procedure TCompany.Print;
begin
Writeln('***********' + Self.FName);
for var index := 0 to Self.FList.Count - 1 do
begin
var OrganizationComponent := Self.FList.Items[index];
OrganizationComponent.print();
end;
end;
procedure TCompany.Remove(OrganizationComponent: IOrganizationComponent);
begin
Self.FList.Remove(OrganizationComponent);
end;
{ TWorkers }
constructor TWorkers.Create(Name: string);
begin
Self.FName := Name
end;
procedure TWorkers.Print;
begin
Writeln(Self.FName)
end;
end.
以上就是组合模式的玩法,古人说书上得来终觉浅,绝知此事要躬行,所以如果你在看完代码还是无法理解的话,那我建议你动手写一遍。
这个设计模式其实不复杂,我在做的时候有好几次都卡壳了,所以最好还是动手写一遍。最后放一张运行效果图
xiaoguotu