多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > 設計模式(結構型)之組合模式(Composite Pattern)

設計模式(結構型)之組合模式(Composite Pattern)

來源:程序員人生   發布時間:2015-07-14 13:20:08 閱讀次數:2432次

PS1句:終究還是選擇CSDN來整理發表這幾年的知識點,該文章平行遷移到CSDN。由于CSDN也支持MarkDown語法了,牛逼啊!

【工匠若水 http://blog.csdn.net/yanbober】 瀏覽前1篇《設計模式(結構型)之橋接模式(Bridge Pattern)》 http://blog.csdn.net/yanbober/article/details/45366781

概述

組合模式又叫做部份-整體模式,使我們在樹型結構的問題中模糊簡單元素和復雜元素的概念,客戶程序可以像處理簡單元素1樣來處理復雜的元素,從而使得客戶程序與復雜元素的內部結構解耦。組合模式可以優化處理遞歸或分級數據結構。有許多關于分級數據結構的例子,使得組合模式非常有用武之地。

核心

概念: 組合多個對象構成樹形結構以表示具有“整體―部份”關系的層次結構。組合模式對單個對象(即葉子對象)和組合對象(即容器對象)的使用具有1致性,組合模式又可以稱為“整體―部份”(Part-Whole)模式,它是1種對象結構型模式。

重點: 組合模式結構重要核心模塊:

抽象構件(Component)

組合中的對象聲明接口,在適當的情況下實現所有類共有接口的默許行動。聲明1個接口用于訪問和管理Component子部件。

樹葉構件(Leaf)

在組合中表示樹的葉子結點對象,葉子結點沒有子結點。

容器構件(Composite)

定義有枝節點的部件,在Component接口中實現與子部件有關操作,如增加(add)和刪除(remove)等。

核心:組合模式的關鍵是定義1個抽象構件類,它既可以代表Leaf,又可以代表Composite,而客戶端針對該抽象構件類進行編程,不必知道它到底表示的是葉子還是容器,可以對其進行統1處理。同時容器對象與抽象構件類之間還建立1個聚合關聯關系,在容器對象中既可以包括葉子,也能夠包括容器,以此實現遞歸組合,構成1個樹形結構。

使用處景

在具有整體和部份的層次結構中,希望通過1種方式疏忽整體與部份的差異,客戶端可以1致地對待它們。

在1個使用面向對象語言開發的系統中需要處理1個樹形結構。

在1個系統中能夠分離出葉子對象和容器對象,而且它們的類型不固定,需要增加1些新的類型。

程序猿實例

假定問題環境:

就拿Android開發中最多見的1種情形來分析吧。我們有1種需求是遍歷全部cache文件夾下的所有文件及文件夾,打印出來(實際指定不是打印,而是邏輯操作,這里演示而已)。以下我們先不使用組合模式。

package yanbober.github.io; import java.util.ArrayList; import java.util.List; class MediaFile { private String mName; private String mDescription; public MediaFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public String toString() { return "MediaFile# Name="+mName+", Description="+mDescription; } } class OfficeFile { private String mName; private String mDescription; public OfficeFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public String toString() { return "OfficeFile# Name="+mName+", Description="+mDescription; } } class PackageFile { private String mName; private String mDescription; public PackageFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public String toString() { return "PackageFile# Name="+mName+", Description="+mDescription; } } class BaseFolder { private String mName; private String mDescription; private List<BaseFolder> mBaseFolderList = new ArrayList<>(); private List<MediaFile> mMediaFileList = new ArrayList<>(); private List<OfficeFile> mOfficeFileList = new ArrayList<>(); private List<PackageFile> mPackageFileList = new ArrayList<>(); public BaseFolder(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } public void addBaseFolder(BaseFolder baseFolder) { mBaseFolderList.add(baseFolder); } public void addMediaFile(MediaFile mediaFile) { mMediaFileList.add(mediaFile); } public void addOfficeFile(OfficeFile officeFile) { mOfficeFileList.add(officeFile); } public void addPackageFile(PackageFile packageFile) { mPackageFileList.add(packageFile); } @Override public String toString() { StringBuilder builder = new StringBuilder("*****BaseFolder# enter folder is:"+mName+" "); for (BaseFolder baseFolder : mBaseFolderList) { builder.append(baseFolder.toString()+" "); } for (MediaFile mediaFile : mMediaFileList) { builder.append(mediaFile.toString()+" "); } for (OfficeFile officeFile : mOfficeFileList) { builder.append(officeFile.toString()+" "); } for (PackageFile packageFile : mPackageFileList) { builder.append(packageFile.toString()+" "); } return builder.toString(); } } public class Main { public static void main(String[] args) { BaseFolder folder = new BaseFolder("cache", "app cache dir."); MediaFile mediaFile = new MediaFile("test.png", "test picture."); folder.addMediaFile(mediaFile); mediaFile = new MediaFile("haha.mp4", "test video."); folder.addMediaFile(mediaFile); PackageFile packageFile = new PackageFile("yanbo.apk", "an android application."); folder.addPackageFile(packageFile); BaseFolder childDir = new BaseFolder("word", "office dir."); OfficeFile officeFile = new OfficeFile("rrrr.doc", "office doc file."); childDir.addOfficeFile(officeFile); folder.addBaseFolder(childDir); System.out.println(folder.toString()); } }

有了如上實現那末問題來了。。。

如上代碼你會發現客戶端代碼過量地依賴于容器對象復雜的內部實現結構,容器對象內部實現結構的變化將引發客戶代碼的頻繁變化,帶來了代碼保護復雜、可擴大性差等弊端。組合模式的引入將在1定程度上解決這些問題。

準么辦?升個級唄,用1下組合模式。

升個級吧

給上面代碼來個重構? 那就依照組合模式結構重要核心模塊來對上面代碼升級重構1把吧。

package yanbober.github.io; import java.util.ArrayList; import java.util.List; abstract class AbstractComponent { public abstract void add(AbstractComponent c); public abstract AbstractComponent get(int index); public abstract String getString(); } class MediaFile extends AbstractComponent { private String mName; private String mDescription; public MediaFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public void add(AbstractComponent c) { //unused } @Override public AbstractComponent get(int index) { return null; } @Override public String getString() { return "MediaFile# Name="+mName+", Description="+mDescription; } } class OfficeFile extends AbstractComponent { private String mName; private String mDescription; public OfficeFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public void add(AbstractComponent c) { //unused } @Override public AbstractComponent get(int index) { return null; } @Override public String getString() { return "OfficeFile# Name="+mName+", Description="+mDescription; } } class PackageFile extends AbstractComponent { private String mName; private String mDescription; public PackageFile(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public void add(AbstractComponent c) { //unused } @Override public AbstractComponent get(int index) { return null; } @Override public String getString() { return "PackageFile# Name="+mName+", Description="+mDescription; } } class BaseFolder extends AbstractComponent { private String mName; private String mDescription; private List<AbstractComponent> abstractComponents = new ArrayList<>(); public BaseFolder(String mName, String mDescription) { this.mName = mName; this.mDescription = mDescription; } @Override public void add(AbstractComponent c) { abstractComponents.add(c); } @Override public AbstractComponent get(int index) { return abstractComponents.get(index); } @Override public String getString() { StringBuilder builder = new StringBuilder("*****BaseFolder# enter folder is:"+mName+" "); for (AbstractComponent baseFolder : abstractComponents) { builder.append(baseFolder.getString()+" "); } return builder.toString(); } } public class Main { public static void main(String[] args) { AbstractComponent folder = new BaseFolder("cache", "app cache dir."); AbstractComponent mediaFile = new MediaFile("test.png", "test picture."); folder.add(mediaFile); mediaFile = new MediaFile("haha.mp4", "test video."); folder.add(mediaFile); AbstractComponent packageFile = new PackageFile("yanbo.apk", "an android application."); folder.add(packageFile); BaseFolder childDir = new BaseFolder("word", "office dir."); AbstractComponent officeFile = new OfficeFile("rrrr.doc", "office doc file."); childDir.add(officeFile); folder.add(childDir); System.out.println(folder.getString()); } }

上例通過組合模式代碼具有了良好的可擴大性,在增加新的文件類型時,不必修改現有類庫代碼,只需增加1個新的文件類作為AbstractFile類的子類便可(不用在BaseFolder中再去修改添加),但是由于在AbstractFile中聲明了大量用于管理和訪問成員構件的方法,例如add(),我們需要在新增的文件類中實現這些方法,提供對應的毛病提示和異常處理。這下你就明白了,其實如上代碼還可以繼續優化的,把每一個子類實現的毛病提示和異常處理寫入抽象的基類中作為默許處理,這樣也能夠減少代碼重復。哈哈。

總結1把

當發現需求中是體現部份與整體層次結構時,和你希望用戶可以疏忽組合對象與單個對象的不同,統1地使用組合結構中的所有對象時,就應當斟酌組合模式了。

組合模式優點以下:

  • 組合模式可以清楚地定義分層次的復雜對象,表示對象的全部或部份層次,它讓客戶端疏忽了層次的差異,方便對全部層次結構進行控制。
  • 客戶端可以1致地使用1個組合結構或其中單個對象,沒必要關心處理的是單個對象還是全部組合結構,簡化了客戶端代碼。
  • 在組合模式中增加新的容器構件和葉子構件都很方便,不必對現有類庫進行任何修改,符合“開閉原則”。
  • 組合模式為樹形結構的面向對象實現提供了1種靈活的解決方案,通過葉子對象和容器對象的遞歸組合,可以構成復雜的樹形結構,但對樹形結構的控制卻非常簡單。

組合模式缺點以下:

  • 在增加新構件時很難對容器中的構件類型進行限制。有時候我們希望1個容器中只能有某些特定類型的對象,例如在某個文件夾中只能包括文本文件,使用組合模式時,不能依賴類型系統來施加這些束縛,由于它們都來自于相同的抽象層,在這類情況下,必須通過在運行時進行類型檢查來實現,這個實現進程較為復雜。

【工匠若水 http://blog.csdn.net/yanbober】 繼續瀏覽《設計模式(結構型)之裝潢者模式(Decorator Pattern)》 http://blog.csdn.net/yanbober/article/details/45395747

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 精品久久成人免费第三区 | 精品国产日韩久久亚洲 | 国产热视频 | 欧美在线观看一区二区三区 | 亚洲经典在线观看 | 午夜视频日本 | 欧美久久久久久久一区二区三区 | 日日夜夜天天久久 | 羞羞动漫免费网站 | 中文字幕日韩欧美一区二区三区 | 噜噜噜噜噜视频在线观看 | 国产成人a一在线观看 | 中文字幕乱码无线码在线 | 国产亚洲欧美久久久久 | 亚洲精品一区久久狠狠欧美 | 日本久本草精品 | 最近中文字幕版免费 | 精品久久综合一区二区 | 亚洲免费视 | 国产在线欧美日韩精品一区二区 | 欧美激情区 | 亚洲午夜国产精品无卡 | 一本大道道香蕉免费 | 欧美日韩国产成人精品 | 欧美色惰aⅴ | 一级做a爰片久久毛片 | 国内外精品免费视频 | 一级做a爰片性色毛片男 | 欧美人成在线观看ccc36 | 综合亚洲欧美 | 色综合小说久久综合图片 | 精品国产一区二区三区免费看 | 春意午夜影院 | 亚洲 欧美 综合 | 国产三级视频 | 欧美亚洲国产成人不卡 | 欧美日韩亚洲综合在线一区二区 | 在线观看91精品国产性色 | 最近中文字幕资源 | 欧美 日韩 国产 成人 在线观看 | 91久久偷偷做嫩草影院 |