組合模式
通過將單個(gè)對象和組合對象用相同的接口表示恤批,使得客戶端對單個(gè)對象和組合對象保存一致的處理弃揽,屬于結(jié)構(gòu)型模式。
使用場景
- 希望客戶端可以忽略單個(gè)和整體對象的差異
- 對象層次具備整體和部分,通常成樹形結(jié)構(gòu)(公司的組織架構(gòu),操作系統(tǒng)的文件目錄茅茂, 樹形菜單等)
具體實(shí)現(xiàn)(2種)
主要是部分和整體實(shí)現(xiàn)公共的接口捏萍。
- 透明實(shí)現(xiàn)(部分與整體差異小,不經(jīng)常變動(dòng))空闲,接口擁有所有方法令杈,沒有權(quán)限或調(diào)用功能直接拋出異常
- 安全實(shí)現(xiàn)(部分與整體差異較大),接口只有公共方法碴倾,各自有獨(dú)立的方法
透明模式demo(對比安全模式逗噩,主要在接口定義上不一樣)
package com.lovingmo.spdemo01.demo.compose;
public abstract class Directory {
public void show(){};
// 這個(gè)方法在File中用不上,但是會(huì)被繼承或?qū)崿F(xiàn)跌榔,調(diào)用拋出異常
public Directory add(Directory directory ){
throw new RuntimeException("添加異常");
}
}
安全模式demo
Directory.java
package com.lovingmo.spdemo01.demo.compose;
public abstract class Directory {
public void show(){};
}
File.java
package com.lovingmo.spdemo01.demo.compose;
public class File extends Directory{
private String name;
public File(String name) {
this.name = name;
}
@Override
public void show() {
System.out.println(this.name);
}
}
Folder.java
package com.lovingmo.spdemo01.demo.compose;
import java.util.ArrayList;
import java.util.List;
public class Folder extends Directory{
private List<Directory> directories;
private String name;
private Integer level;
public Folder(String name, int level) {
this.name = name;
this.level = level;
this.directories = new ArrayList<>();
}
public Directory add(Directory directory){
directories.add(directory);
return directory;
}
@Override
public void show() {
System.out.println(this.name);
for (Directory directory : directories){
if(this.level != null){
for (int a = 0; a< this.level; a++){
System.out.print(" ");
}
for(int i = 0; i < this.level; i ++){
//每一行開始打印一個(gè)+號(hào)
if(i == 0){ System.out.print("+"); }
System.out.print("-");
}
}
directory.show();
}
}
}
Test.java
package com.lovingmo.spdemo01.demo.compose;
public class Test {
public static void main(String[] args) {
File idea = new File("idea.exe");
File mysql = new File("mysql.exe");
Folder games = new Folder("游戲", 2);
File lol = new File("lol.exe");
File dnf = new File("dnf.exe");
games.add(lol);
games.add(dnf);
Folder root = new Folder("D:/", 1);
root.add(games);
root.add(idea);
root.add(mysql);
root.show();
}
}
源碼中的使用
- HashMap中的put()與putAll()
- ArrayList中的add()與addAll()
優(yōu)點(diǎn)
- 清楚的定義分層次的復(fù)雜對象异雁,表示對象的全部和部分層次
- 讓客戶端忽略對層次的差異,方便對整個(gè)層次結(jié)構(gòu)進(jìn)行控制
- 簡化客戶端代碼
- 符合開閉原則
缺點(diǎn)
- 限制類型時(shí)較為復(fù)雜
- 設(shè)計(jì)時(shí)更加抽象