1.定义
又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。
2.理解
可以简单理解为树状结构,访问树中的任何一个节点和访问树是同样的操作。 组合模式包含以下主要角色。
抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于实现抽象构件角色中 声明的公共接口。树枝构件(Composite)角色:是组合中的分支节点对象,它有子节点。它实现了抽象构件角色中声明的接口,它的主要作用是存储和管理子部件,通常包含Add()、Remove()、GetChild() 等方法。
3.两种模式
1.透明方式:
在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。但其缺点是:树叶构件本来没有Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。
2.安全方式
在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题,但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。
4.java实现透明模式
public class CompositePattern {
public static void main(String
[] args
) {
IDirectory root
= new Directory("根目录");
IDirectory first
= new Directory("第一层目录");
IDirectory second
= new Directory("第二层目录");
IDirectory index1
= new Index("指标1");
root
.add(first
);
first
.add(second
);
second
.add(index1
);
first
.operation();
}
}
interface IDirectory {
void add(IDirectory directory
);
void remove(IDirectory directory
);
Set
<IDirectory> chirdren();
void operation();
}
class Directory implements IDirectory{
private Set
<IDirectory> set
= new HashSet<>();
public String name
;
public Directory(String name
){
this.name
= name
;
}
@Override
public void add(IDirectory directory
) {
this.set
.add(directory
);
}
@Override
public void remove(IDirectory directory
) {
this.set
.remove(directory
);
}
@Override
public Set
<IDirectory> chirdren() {
return this.set
;
}
@Override
public void operation() {
System
.out
.println("目录:"+this.name
);
}
}
class Index implements IDirectory{
public String name
;
public Index(String name
){
this.name
= name
;
}
@Override
public void add(IDirectory directory
) {
}
@Override
public void remove(IDirectory directory
) {
}
@Override
public Set
<IDirectory> chirdren() {
return null
;
}
@Override
public void operation() {
System
.out
.println("指标:"+this.name
);
}
}
5.golang实现安全模式
func main() {
root
:= &Directory
{Name
: "根目录"}
first
:= &Directory
{Name
: "第一层目录"}
second
:= &Directory
{Name
: "第二层目录"}
index1
:= &Index
{Name
: "指标1"}
root
.Add(first
)
first
.Add(second
)
second
.Add(index1
)
first
.Operation()
index1
.Operation()
}
type IDirectory
interface {
Operation()
}
type Index
struct {
Name
string
}
func (index
*Index
) Operation() {
fmt
.Println("指标:",index
.Name
)
}
type Directory
struct {
Name
string
Children
[]IDirectory
}
func (d
*Directory
) Operation() {
fmt
.Println("目录:",d
.Name
)
}
func (d
*Directory
) Add(child IDirectory
) {
d
.Children
= append(d
.Children
, child
)
}
func (d
*Directory
) GetChildren() []IDirectory
{
return d
.Children
}