Composite模式(組合設計模式)
阿新 • • 發佈:2018-12-17
Composite 設計模式?
在計算機的檔案系統中,有“資料夾”的概念(在有些作業系統(Linux作業系統)中,也稱為“目錄”)。資料夾裡面既可以放入檔案,也可以放入其他資料夾(子資料夾)。在子資料夾中,一樣地既可以放入檔案,也可以放入子資料夾。可以說,資料夾是形成了一種容器結構、遞迴結構。
結構模式:能夠使容器與內容具有一致性,創造出遞迴結構的模式就是Composite模式。
關注點:使用Composite模式可以使容器與內容具有一致性,也可以稱其為多個和單個的一致性,即將多個物件結合在一起,當作一個物件進行處理。
理清職責
- 到處存在的遞迴結構:
- 在視窗系統中,一個視窗可以含有一個子視窗, 2.在文章的列表中,各列表之間可以相互巢狀,這也是一種遞迴結構。 3.將多條計算機命令合併為一條巨集命令時,如果使用遞迴結構實現巨集命。 4.樹結構的資料結構都適用Composite模式。
實現:演示資料夾 檔案子項之間的層次關係 名字===================>>>說明 Entry || 抽象類,用來實現File類和Directory類的一致性 File || 表示檔案的類 Directory || 表示資料夾的類 FileTreatementException || 表示向檔案中增加Entry時發生的異常的類 Main || 測試程式行為的類
- Add()方法的存在位置:
- 存在Entry 丟擲異常。
- 存在Entry 中什麼也不做。
- 宣告在Entry中為抽象方法 不去實現。
- 直接定義在Directory類中,但是需要關注型別之間的轉換。
UML
類圖:
Code
- Entry
···
public abstract class Entry {
/** * 1. 檔名 * 2. 檔案大小 * @return */ public abstract String getName(); public abstract int getSize(); /** * Directory 增加條目 * File 不能增加條目 */ public Entry add(Entry entry)throws FileTreatementException{ throw new FileTreatementException(); } public void printList(){ printList(""); } protected abstract void printList(String prefix); @Override public String toString() { return getName()+"("+getSize()+")"; }
}
···
- File
public class File extends Entry {
private String name;
private int size;
public File(String name, int size) {
this.name = name;
this.size = size;
}
@Override
public String getName() {
return name;
}
@Override
public int getSize() {
return size;
}
@Override
protected void printList(String prefix) {
System.out.println(prefix+"/"+this);
}
}
- Directory
public class Directory extends Entry {
private String name;
private List<Entry> directory=new ArrayList<>();
public Directory(String name) {
this.name = name;
}
@Override
public Entry add(Entry entry) throws FileTreatementException {
directory.add(entry);
return this;
}
@Override
public String getName() {
return name;
}
/**
* getSize() | printList(String prefix)
*
* 都會遞迴去遍歷下面可能存在的 目錄或者檔案的子項
*/
@Override
public int getSize() {
int size=0;
Iterator<Entry> it = directory.iterator();
while (it.hasNext()){
// 這裡的Entry 可能是目錄 也可能是檔案
Entry next = it.next();
size+=next.getSize();
}
return size;
}
@Override
protected void printList(String prefix) {
// 這裡的 prefix是一個引用 this將會呼叫tostring()方法 又會繼續呼叫getName() getSize()方法
System.out.println(prefix+"/"+this);
Iterator<Entry> it = directory.iterator();
while(it.hasNext()){
// 這裡的Entry 可能是目錄 也可能是檔案
Entry next = it.next();
next.printList(prefix+"/"+this);
}
}
}
- FileTreatementException
public class FileTreatementException extends Exception {
public FileTreatementException() {
}
public FileTreatementException(String message) {
super(message);
}
}
- 定義的目的結構:
start +++++++++++
/root(16000)
/root(16000)/bin(16000)
/root(16000)/bin(16000)/vi(1000)
/root(16000)/bin(16000)/notepaid(15000)
/root(16000)/temp(0)
/root(16000)/user(0)
- MainT
public class MainT {
public static void main(String[] args) throws FileTreatementException{
System.out.println("start +++++++++++");
Directory rootdir=new Directory("root");
Directory bindir = new Directory("bin");
Directory tempdir = new Directory("temp");
Directory userdir = new Directory("user");
rootdir.add(bindir);
rootdir.add(tempdir);
rootdir.add(userdir);
bindir.add(new File("vi",1000));
bindir.add(new File("notepaid",15000));
rootdir.printList();
}
}