|
Design Pattern - Composite
|
| (史帝芬, 2007/06/03, hi.steven@gmail.com) |
在看Composite Pattern之前,建議先看一下Iterator Pattern,
Iterator Pattern可巡訪聚合物件裡的元素,而這些元素是同類別的。Composite Pattern也會有巡訪的動作,
巡訪的類別會有個別類別物件和組合類別物件,但是Composite Pattern會將物件組織成樹狀結構,
並且讓外界以一致性的方式對待個別類別物件和組合類別物件。下圖是GoF書中Composite Pattern的類別圖,
個別類別Left和組合類別Composite都繼承Component,透過這樣的繼承關係,才能使得巡訪時,
可將個別類別物件及組合類別物件視為相同的類別。
![]() 這裡我們將以檔案系統為例,實作Composite Pattern,類別圖如下。 個別類別File及組合類別Directory都繼承Entry,Directory可包含多個File及多個Directory, 實際巡訪元素時,操作的是Entry,所以,也就是將這兩個不同類別的物件視為相同,實際上的 實作是在File和Directory中, 而非在Entry。 ![]()
using System;
using System.Collections;
namespace Composite
{
public abstract class Entry
{
private string name;
public Entry(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
set { name = value; }
}
public virtual int Size
{
get { return 0; }
}
public virtual Entry add(Entry entry)
{
throw new Exception();
}
public abstract void printList(string prefix);
public void printList()
{
printList("");
}
}
public class File : Entry
{
private int size;
public File(string name, int size)
: base(name)
{
this.size = size;
}
public override int Size
{
get { return size; }
}
public override void printList(string prefix)
{
Console.WriteLine("{0}/{1} ({2})", prefix, Name, Size);
}
}
public class Directory : Entry
{
private ArrayList directory = new ArrayList();
public Directory(string name)
: base(name)
{
}
public override int Size
{
get
{
int size = 0;
foreach (Entry entry in directory)
{
size += entry.Size;
}
return size;
}
}
public override Entry add(Entry entry)
{
directory.Add(entry);
return this;
}
public override void printList(string prefix)
{
Console.WriteLine("{0}/{1} ({2})", prefix, Name, Size);
foreach (Entry entry in directory)
{
entry.printList(prefix + "/" + Name);
}
}
}
class Program
{
static void Main(string[] args)
{
Directory windows = new Directory("Windows");
Directory system32 = new Directory("system32");
windows.add(system32);
windows.add(new File("desktop.ini", 923));
windows.add(new File("TASKMAN.EXE", 15360));
system32.add(new File("shutdown.exe", 23552));
windows.printList();
Console.ReadLine();
}
}
}
/Windows (39835) /Windows/system32 (23552) /Windows/system32/shutdown.exe (23552) /Windows/desktop.ini (923) /Windows/TASKMAN.EXE (15360) |