第11章はCompositeパターン。これは分かりやすい上に利用頻度も高そうなデザインパターンです。
再帰的なクラス構造が出てきたら、このパターンが適用できないかを常に意識したほうがいいでしょう。
- Leaf役とComposite役とで共通な実装にしたければComponentに実装し、
- それぞれで違う実装にしたければComponentで定義(宣言)だけして、LeafとCompositeそれぞれで実装すればいい
add/remove/getChild は、例と同じようにComponent(親)にエラーとして実装し、Compositeでオーバーライドするのが好きです。
実行結果
Making root entries... /root (30000) /root/bin (30000) /root/bin/vi (10000) /root/bin/latex (20000) /root/tmp (0) /root/usr (0) Making user entries... /root (31500) /root/bin (30000) /root/bin/vi (10000) /root/bin/latex (20000) /root/tmp (0) /root/usr (1500) /root/usr/yuki (300) /root/usr/yuki/diary.html (100) /root/usr/yuki/Composite.java (200) /root/usr/hanako (300) /root/usr/hanako/memo.tex (300) /root/usr/tomura (900) /root/usr/tomura/game.doc (400) /root/usr/tomura/junk.mail (500) #11-2 /root (100) /root/usr (100) /root/usr/yuki (100) /root/usr/yuki/Composite.java (100) file = /root/usr/yuki/Composite.java yuki = /root/usr/yuki
ソースコード
#!/usr/bin/env python # -*- coding: utf8 -*- class FileTreatmentException(Exception): def __init__(self): print "FileTreatmentException raised" class Entry: def __init__(self): raise Exception("Abstract class") def getName(self): raise NotImplementedError def getSize(self): raise NotImplementedError def printList(self): self._printList("") def _printList(self, prefix): raise NotImplementedError def add(self, entry): raise FileTreatmentException def __str__(self): return "%s (%d)" % (self.getName(), self.getSize()) #11-2 def getFullName(self): entry = self fullname = "" while entry is not None: fullname = "/" + entry.getName() + fullname entry = entry.parent return fullname class File(Entry): def __init__(self, name, size): self.__name = name self.__size = size self.parent = None def getName(self): return self.__name def getSize(self): return self.__size def _printList(self, prefix): print prefix+"/"+str(self) class Directory(Entry): def __init__(self, name): self.__name = name self.directory = [] self.parent = None def getName(self): return self.__name def getSize(self): return sum([e.getSize() for e in self.directory]) def _printList(self, prefix): print prefix+"/"+str(self) for e in self.directory: e._printList(prefix+"/"+self.__name) def add(self, entry): self.directory.append(entry) entry.parent = self #11-2 def main(): print "Making root entries..." m_rootdir = Directory("root") m_bindir = Directory("bin") m_tmpdir = Directory("tmp") m_usrdir = Directory("usr") m_rootdir.add(m_bindir) m_rootdir.add(m_tmpdir) m_rootdir.add(m_usrdir) m_bindir.add(File("vi", 10000)) m_bindir.add(File("latex", 20000)) m_rootdir.printList() print "" print "Making user entries..." m_yuki = Directory("yuki") m_hanako = Directory("hanako") m_tomura = Directory("tomura") m_usrdir.add(m_yuki) m_usrdir.add(m_hanako) m_usrdir.add(m_tomura) m_yuki.add(File("diary.html", 100)) m_yuki.add(File("Composite.java", 200)) m_hanako.add(File("memo.tex", 300)) m_tomura.add(File("game.doc", 400)) m_tomura.add(File("junk.mail", 500)) m_rootdir.printList() #11-2 print "" print "#11-2" m_rootdir = Directory("root"); m_usrdir = Directory("usr"); m_rootdir.add(m_usrdir); m_yuki = Directory("yuki"); m_usrdir.add(m_yuki); m_file = File("Composite.java", 100); m_yuki.add(m_file); m_rootdir.printList(); print "file = " + m_file.getFullName() print "yuki = " + m_yuki.getFullName() if __name__=='__main__': main()
0 件のコメント:
コメントを投稿