也稱爲總體-部分模式, 經過將單個對象(葉子節點)和組合對象(樹枝節點)用相同的接口進行表示
做用: 使客戶端對單個對象和組合對象保持一致的方式處理。屬於結構型模式java
使用場景:
一、但願客戶端能夠忽略組合對象與單個對象的差別時
二、對象層次具有總體和部分, 呈樹形結構(如樹形菜單, 操做系統目錄結構, 公司組織架構等)設計模式
public abstract class CourseComponent { public void addChild(CourseComponent catalogComponent) { throw new UnsupportedOperationException("不支持添加操做"); } public void removeChild(CourseComponent catalogComponent) { throw new UnsupportedOperationException("不支持刪除操做"); } public String getName(CourseComponent catalogComponent) { throw new UnsupportedOperationException("不支持獲取名稱操做"); } public double getPrice(CourseComponent catalogComponent) { throw new UnsupportedOperationException("不支持獲取價格操做"); } public void print() { throw new UnsupportedOperationException("不支持打印操做"); } }
public class Course extends CourseComponent{ private String name; private double price; public Course(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String getName(CourseComponent catalogComponent) { return this.name; } @Override public double getPrice(CourseComponent catalogComponent) { return this.price; } @Override public void print() { System.out.println(name + "¥:" + price + "元"); } }
public class CoursePackage extends CourseComponent { private List<CourseComponent> items = new ArrayList<>(); private String name; private Integer level; public CoursePackage(String name, Integer level) { this.name = name; this.level = level; } @Override public void addChild(CourseComponent catalogComponent) { items.add(catalogComponent); } @Override public void removeChild(CourseComponent catalogComponent) { items.remove(catalogComponent); } @Override public String getName(CourseComponent catalogComponent) { return this.name; } @Override public void print() { System.out.println(this.name); for (CourseComponent catalogComponent : items) { //控制顯示格式 if (this.level != null) { for (int i = 0; i < this.level; i++) { // 打印空格控制格式 System.out.print("==="); } for (int i = 0; i < this.level; i++) { // 每一行開始打印一個+號 if (i == 0) { System.out.print("+"); } System.out.print("-"); } } //打印標題 catalogComponent.print(); } } }
public static void main(String[] args) { System.out.println("=============透明的組合模式=============="); CourseComponent javaBase = new Course("Java入門課程", 8280); CourseComponent ai = new Course("人工智能", 5000); CourseComponent packageCourse = new CoursePackage("Java架構師課程", 2); CourseComponent design = new Course("Java設計模式", 1580); CourseComponent source = new Course("源碼分析", 2000); CourseComponent softSkill = new Course("軟技能", 3000); packageCourse.addChild(design); packageCourse.addChild(source); packageCourse.addChild(softSkill); CourseComponent catalog = new CoursePackage("課程主目錄", 1); catalog.addChild(javaBase); catalog.addChild(ai); catalog.addChild(packageCourse); catalog.print(); }
================================================================================安全
public abstract class Directory { protected String name; public Directory(String name) { this.name = name; } /** * 展現 */ public abstract void show(); }
public class File extends Directory { public File(String name) { super(name); } @Override public void show() { System.out.println(this.name); } }
public class Folder extends Directory { private List<Directory> dirs; private Integer level; public Folder(String name, Integer level) { super(name); this.level = level; this.dirs = new ArrayList<>(); } @Override public void show() { System.out.println(this.name); for (Directory dir : this.dirs) { //控制顯示格式 if (this.level != null) { for (int i = 0; i < this.level; i++) { //打印空格控制格式 System.out.print("=="); } for (int i = 0; i < this.level; i++) { //每一行開始打印一個+號 if (i == 0) { System.out.print("+"); } System.out.print("-"); } } //打印名稱 dir.show(); } } public boolean add(Directory dir) { return this.dirs.add(dir); } public boolean remove(Directory dir) { return this.dirs.remove(dir); } public Directory get(int index) { return this.dirs.get(index); } public void list() { for (Directory dir : this.dirs) { System.out.println(dir.name); } } }
public static void main(String[] args) { System.out.println("============安全組合模式==========="); File qq = new File("QQ.exe"); File weChat = new File("weChat.exe"); Folder office = new Folder("辦公軟件", 2); File word = new File("Word.exe"); File ppt = new File("PowerPoint.exe"); File excel = new File("Excel.exe"); office.add(word); office.add(ppt); office.add(excel); Folder wps = new Folder("金山軟件", 3); wps.add(new File("WPS.exe")); office.add(wps); Folder root = new Folder("根目錄", 1); root.add(qq); root.add(weChat); root.add(office); System.out.println("=============show()方法============="); root.show(); System.out.println("=============list()方法============="); root.list(); }
源碼中的運用 HashMap的putAll方法;ArrayList的addAll方法;架構
Mybatis中的: WhereSqlNodeide
優勢:
一、清楚地定義分層次的複雜對象, 表示對象的所有或部分層次
二、讓客戶端忽略了層次的差別, 方便對整個層次結構進行控制
三、簡化了客戶端代碼
四、符合開閉原則
缺點:
一、限制類型時會較爲複雜
二、使設計變得更加抽象源碼分析