2011年12月30日 星期五

阿班私房菜-Design Pattern(DP)初探使用Python (1)


Design Patterns: Elements of Reusable Object-Oriented Software

最近使用Python 寫程式,心血來潮,使用 (DP) 套用看看。
以 Factory worker 為例。
首先建立一個物件Worker 包含姓名、屬性等等。
class Worker:
    def __init__(self, name=None):
        self.name = capfirst(name) if name else "The worker"
    def getName(self):
        return self.name
    def attrib(self):        return "Worker"
    def lookandfeel(self):
        print "%s is a %s" % (self.name, self.attrib())

Designer與Engineer繼承它,並覆寫attrib() Method。
class Designer(Worker):
    def attrib(self):        return "Designer"
class Engineer(Worker):
    def attrib(self):        return "Engineer"

當使用各自物件來建立,並執行lookandfeel() 時,會呼叫各自的attrib method。
以下使用 factory pattern 來實作僱用workers 的容器物件。
# factory pattern
class Factory:
    type_designer = 1
    type_engineer = 2
    def __init__(self):
        self.workers = []
    def employ(self, worker_type, name=None):
        if worker_type == Factory.type_designer:
            self.workers.append(Designer(name))
        elif worker_type == Factory.type_engineer:
            self.workers.append(Engineer(name))
    def workerCount(self):
        return len(self.workers)
    def browse(self):
        for a in self.workers:
            a.lookandfeel()
z = Factory()
z.employ(Factory.type_designer)
z.employ(Factory.type_designer, 'bill')
z.employ(Factory.type_engineer, 'sue')
z.browse()

執行結果:
$ python factory_dp1.py
The worker is a Designer
Bill is a Designer
Sue is a Engineer

承上篇重構一文:我們來重構一下它,並加入singleton pattern(利用@staticmethod 來實作)。
class Factory:
    # class static variable
    type_designer = "1"
    type_engineer = "2"
    _Factoryself = None
    _factorydict = {
           type_designer: Designer,
           type_engineer: Engineer,
        }
    def __init__(self):
        self.workers = []

    @staticmethod
    def singleton():
        if Factory._Factoryself == None:
            Factory._Factoryself = Factory()
        return Factory._Factoryself



    def employ(self, worker_type, name=None):
        caller = Factory._factorydict.get(worker_type)
        if caller:
            self.workers.append(caller(name))
        return None



    def workerCount(self):
        return len(self.workers)

    def browse(self):
        i = 0
        for a in self.workers:
            print " - Worker[%s]:%s" % (i, a.getLookandfeel())
            i+=1

def main():
    f = Factory.singleton()
    f2 = Factory.singleton()
    if f == f2:
        print "* Singleton pattern of Factory"



    print "* Factory pattern to employ"
    f.employ(Factory.type_designer)
    f.employ(Factory.type_designer, 'Bill')
    f.employ(Factory.type_engineer, 'Sue')
    print "* Factory pattern to browse"
    f.browse()
    print "* The factory has %s workers." % f.workerCount()

if __name__ == "__main__":
    main()

小結

使用python 來寫DP程式,功能強大,自由度高;
但這意味,寫其程式時,要有其紀律,遵守一定規範(coding convention)來寫;
不然程式會變得非常難讀及維護。 最近上列範例程式均可在github-class_dp中找到。
上述範例還可進一步,重構或修改為工廠人員管理系統的雛形,留待有興趣的讀者們來添加!

沒有留言: