java合成模式之神奇的樹(shù)結(jié)構(gòu)
什么是合成模式
以下是互聯(lián)網(wǎng)的解釋。
合成模式屬于對(duì)象的結(jié)構(gòu)模式,有時(shí)又叫做“部分——整體”模式。合成模式將對(duì)象組織到樹(shù)結(jié)構(gòu)中,可以用來(lái)描述整體與部分的關(guān)系。合成模式可以使客戶(hù)端將單純?cè)嘏c復(fù)合元素同等看待。
經(jīng)常會(huì)出現(xiàn)有樹(shù)結(jié)構(gòu)的情況 , 其中由單獨(dú)的對(duì)象或者單獨(dú)對(duì)象組成的合成對(duì)象組成 , 此時(shí)就需要利用一種方式來(lái)完成樹(shù)結(jié)構(gòu)的構(gòu)建工作 .
合成模式提供一個(gè)樹(shù)結(jié)構(gòu)中所有對(duì)象的統(tǒng)一接口 , 規(guī)范樹(shù)中單獨(dú)對(duì)象和合成對(duì)象的構(gòu)建過(guò)程 , 合成模式更像一個(gè)數(shù)據(jù)結(jié)構(gòu) .
合成模式的實(shí)現(xiàn)方式分為透明式和安全式 , 主要區(qū)別在于管理方法是在抽象構(gòu)件中聲明, 還是直接在樹(shù)枝構(gòu)件中定義.
- 透明式 , 管理方法在抽象構(gòu)件中聲明 , 同時(shí)樹(shù)葉節(jié)點(diǎn)需要用平庸的方式實(shí)現(xiàn)管理方法
- 安全式 , 在樹(shù)枝構(gòu)件中直接定義管理方法 , 這樣避免在樹(shù)葉構(gòu)件中進(jìn)行定義 .
設(shè)計(jì)模式和編程語(yǔ)言無(wú)關(guān),但是二當(dāng)家的依然用Java語(yǔ)言去實(shí)戰(zhàn)舉例。
安全式合成模式

- 抽象構(gòu)件(Component)角色:這是一個(gè)抽象角色,它給參加組合的對(duì)象定義出公共的接口及其默認(rèn)行為,可以用來(lái)管理所有的子對(duì)象。合成對(duì)象通常把它所包含的子對(duì)象當(dāng)做類(lèi)型為Component的對(duì)象。在安全式的合成模式里,構(gòu)件角色并不定義出管理子對(duì)象的方法,這一定義由樹(shù)枝構(gòu)件對(duì)象給出。
- 樹(shù)葉構(gòu)件(Leaf)角色:樹(shù)葉對(duì)象沒(méi)有下級(jí)子對(duì)象,定義出參加組合的原始對(duì)象的行為。
- 樹(shù)枝構(gòu)件(Composite)角色:代表參加組合的有下級(jí)子對(duì)象的對(duì)象,并給出樹(shù)枝構(gòu)件對(duì)象的行為。
抽象構(gòu)件(Component)角色
抽象構(gòu)件聲明了葉子和樹(shù)枝都應(yīng)該有的行為。
package com.secondgod.composite;
/**
* 抽象構(gòu)件
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public interface Component {
/**
* 輸出自身的名稱(chēng)
*/
void printStruct(String preStr);
}
樹(shù)葉構(gòu)件(Leaf)角色
樹(shù)葉不會(huì)再有下級(jí)。
package com.secondgod.composite;
import java.text.MessageFormat;
/**
* 樹(shù)葉
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Leaf implements Component {
/**
* 葉子對(duì)象的名字
*/
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void printStruct(String preStr) {
System.out.println(MessageFormat.format("{0}-{1}", preStr, name));
}
}
樹(shù)枝構(gòu)件(Composite)角色
樹(shù)枝可以繼續(xù)長(zhǎng)出樹(shù)枝或者樹(shù)葉,所以要有addChild方法。
package com.secondgod.composite;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
/**
* 樹(shù)枝
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Composite implements Component {
/**
* 用來(lái)存儲(chǔ)組合對(duì)象中包含的子組件對(duì)象
*/
private List<Component> childComponents = new ArrayList<Component>();
/**
* 組合對(duì)象的名字
*/
private String name;
public Composite(String name){
this.name = name;
}
/**
* 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象
* @param child 子構(gòu)件對(duì)象
*/
public void addChild(Component child){
childComponents.add(child);
}
@Override
public void printStruct(String preStr) {
// 先把自己輸出
System.out.println(MessageFormat.format("{0}+{1}", preStr, name));
// 如果還包含有子組件,那么就輸出這些子組件對(duì)象
if (this.childComponents != null) {
// 添加兩個(gè)空格,表示向后縮進(jìn)兩個(gè)空格
preStr += " ";
// 輸出當(dāng)前對(duì)象的子對(duì)象
for (Component c : childComponents) {
// 遞歸輸出每個(gè)子對(duì)象
c.printStruct(preStr);
}
}
}
}
使用
package com.secondgod.composite;
/**
* 測(cè)試
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Client {
public static void main(String[]args){
Composite root = new Composite("生物");
Composite c1 = new Composite("動(dòng)物");
Composite c2 = new Composite("植物");
Leaf leaf1 = new Leaf("貓貓");
Leaf leaf2 = new Leaf("狗狗");
Leaf leaf3 = new Leaf("大樹(shù)");
Leaf leaf4 = new Leaf("小草");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}

執(zhí)行結(jié)果符合預(yù)期。
透明式合成模式

抽象構(gòu)件(Component)角色
生長(zhǎng)樹(shù)枝和樹(shù)葉的方法直接聲明在抽象構(gòu)件里。本例使用抽象類(lèi),其實(shí)也可以使用接口。
package com.secondgod.composite;
/**
* 抽象構(gòu)件
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public abstract class Component {
/**
* 輸出自身的名稱(chēng)
*/
public abstract void printStruct(String preStr);
/**
* 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象
* @param child 子構(gòu)件對(duì)象
*/
public void addChild(Component child){
/**
* 缺省實(shí)現(xiàn),拋出異常,因?yàn)槿~子對(duì)象沒(méi)有此功能
* 或者子組件沒(méi)有實(shí)現(xiàn)這個(gè)功能
*/
throw new UnsupportedOperationException("對(duì)象不支持此功能");
}
}
樹(shù)葉構(gòu)件(Leaf)角色
透明式的葉子從實(shí)現(xiàn)抽象構(gòu)件改成繼承抽象構(gòu)件。如果抽象構(gòu)件是接口,則需要平庸實(shí)現(xiàn)管理子構(gòu)件的方法。
package com.secondgod.composite;
import java.text.MessageFormat;
/**
* 樹(shù)葉
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Leaf extends Component {
/**
* 葉子對(duì)象的名字
*/
private String name;
public Leaf(String name) {
this.name = name;
}
@Override
public void printStruct(String preStr) {
System.out.println(MessageFormat.format("{0}-{1}", preStr, name));
}
}
樹(shù)枝構(gòu)件(Composite)角色
透明式的樹(shù)枝也是從實(shí)現(xiàn)抽象構(gòu)件改為繼承抽象構(gòu)件,這主要跟抽象構(gòu)件是抽象類(lèi)還是接口有關(guān)。
package com.secondgod.composite;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
/**
* 樹(shù)枝
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Composite extends Component {
/**
* 用來(lái)存儲(chǔ)組合對(duì)象中包含的子組件對(duì)象
*/
private List<Component> childComponents = new ArrayList<Component>();
/**
* 組合對(duì)象的名字
*/
private String name;
public Composite(String name){
this.name = name;
}
/**
* 聚集管理方法,增加一個(gè)子構(gòu)件對(duì)象
* @param child 子構(gòu)件對(duì)象
*/
public void addChild(Component child){
childComponents.add(child);
}
@Override
public void printStruct(String preStr) {
// 先把自己輸出
System.out.println(MessageFormat.format("{0}+{1}", preStr, name));
// 如果還包含有子組件,那么就輸出這些子組件對(duì)象
if (this.childComponents != null) {
// 添加兩個(gè)空格,表示向后縮進(jìn)兩個(gè)空格
preStr += " ";
// 輸出當(dāng)前對(duì)象的子對(duì)象
for (Component c : childComponents) {
// 遞歸輸出每個(gè)子對(duì)象
c.printStruct(preStr);
}
}
}
}
使用
客戶(hù)端在使用時(shí),變量可以都聲明為抽象構(gòu)件。
package com.secondgod.composite;
/**
* 測(cè)試
*
* @author 二當(dāng)家的白帽子 https://le-yi.blog.csdn.net/
*/
public class Client {
public static void main(String[]args){
Component root = new Composite("生物");
Component c1 = new Composite("動(dòng)物");
Component c2 = new Composite("植物");
Component leaf1 = new Leaf("貓貓");
Component leaf2 = new Leaf("狗狗");
Component leaf3 = new Leaf("大樹(shù)");
Component leaf4 = new Leaf("小草");
root.addChild(c1);
root.addChild(c2);
c1.addChild(leaf1);
c1.addChild(leaf2);
c2.addChild(leaf3);
c2.addChild(leaf4);
root.printStruct("");
}
}
可以看出,客戶(hù)端無(wú)需再區(qū)分操作的是樹(shù)枝對(duì)象(Composite)還是樹(shù)葉對(duì)象(Leaf)了;對(duì)于客戶(hù)端而言,操作的都是Component對(duì)象。
安全式和透明式
安全式:從客戶(hù)端使用合成模式上看是否更安全,如果是安全的,那么就不會(huì)有發(fā)生誤操作的可能,能訪問(wèn)的方法都是被支持的。
透明式:從客戶(hù)端使用合成模式上,是否需要區(qū)分到底是“樹(shù)枝對(duì)象”還是“樹(shù)葉對(duì)象”。如果是透明的,那就不用區(qū)分,對(duì)于客戶(hù)而言,都是Compoent對(duì)象,具體的類(lèi)型對(duì)于客戶(hù)端而言是透明的,是無(wú)須關(guān)心的。因?yàn)闊o(wú)論樹(shù)葉還是樹(shù)枝,均符合一個(gè)固定的接口。
到底使用安全式還是透明式需要看需求,大家看著辦吧。
以上就是java合成模式之神奇的樹(shù)結(jié)構(gòu)的詳細(xì)內(nèi)容,更多關(guān)于java合成模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- 詳解Java構(gòu)建樹(shù)結(jié)構(gòu)的公共方法
- Java實(shí)現(xiàn)遞歸查詢(xún)樹(shù)結(jié)構(gòu)的示例代碼
- java樹(shù)結(jié)構(gòu)stream工具類(lèi)的示例代碼詳解
- JAVA使用hutool工具實(shí)現(xiàn)查詢(xún)樹(shù)結(jié)構(gòu)數(shù)據(jù)(省市區(qū))
- JAVA如何轉(zhuǎn)換樹(shù)結(jié)構(gòu)數(shù)據(jù)代碼實(shí)例
- JAVA后臺(tái)轉(zhuǎn)換成樹(shù)結(jié)構(gòu)數(shù)據(jù)返回給前端的實(shí)現(xiàn)方法
- Java實(shí)現(xiàn)簡(jiǎn)單樹(shù)結(jié)構(gòu)
- java后端操作樹(shù)結(jié)構(gòu)的案例代碼
相關(guān)文章
JVM執(zhí)行引擎和垃圾回收要點(diǎn)總結(jié)
不論是在問(wèn)題現(xiàn)場(chǎng)還是跳槽面試,我們面對(duì)JVM性能問(wèn)題,依舊會(huì)束手無(wú)辭,它需要你對(duì)Java虛擬機(jī)的實(shí)現(xiàn)和優(yōu)化,有極為深刻的理解。所以我在這里整理了一下 JVM的知識(shí)點(diǎn)。今天說(shuō)說(shuō)虛擬機(jī)執(zhí)行引擎和垃圾回收,都是十足的干貨,請(qǐng)各位看官耐心批閱!2021-06-06
JSON for java快速入門(mén)總結(jié)學(xué)習(xí)
這篇文章主要介紹了JSON for java入門(mén)總結(jié)學(xué)習(xí),有需要的可以了解一下。2016-11-11
Springboot中實(shí)現(xiàn)接口冪等性的4種方案小結(jié)
本文主要介紹了Springboot中實(shí)現(xiàn)接口冪等性,包含數(shù)據(jù)庫(kù)的冪等,數(shù)據(jù)庫(kù)的冪等,Redis的冪等性和Token + 時(shí)間戳的冪等性,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)
下面小編就為大家?guī)?lái)一篇基于多線程并發(fā)的常見(jiàn)問(wèn)題(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
MyBatis中的循環(huán)插入insert foreach問(wèn)題
這篇文章主要介紹了MyBatis中的循環(huán)插入insert foreach問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11
Java實(shí)現(xiàn)求子數(shù)組和的最大值算法示例
這篇文章主要介紹了Java實(shí)現(xiàn)求子數(shù)組和的最大值算法,涉及Java數(shù)組遍歷、判斷、運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下2018-02-02

