Repository: yogykwan/design-patterns-py Branch: master Commit: f2175f1055dd Files: 25 Total size: 29.6 KB Directory structure: gitextract_kmnmm8_p/ ├── .gitignore ├── README.md ├── abstract_factory.py ├── adapter.py ├── bridge.py ├── builder.py ├── chain_of_responsibility.py ├── command.py ├── composite.py ├── decorator.py ├── facade.py ├── factory_method.py ├── flyweight.py ├── interpreter.py ├── iterator.py ├── mediator.py ├── memento.py ├── observer.py ├── prototype.py ├── proxy.py ├── singleton.py ├── state.py ├── strategy.py ├── template_method.py └── visitor.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .idea/ ================================================ FILE: README.md ================================================ # design-patterns 《大话设计模式》中23种设计模式案例的Python版本实现。样例忠于原书,某些地方根据Python特性做了修改,如abstract、private、reflection等。 ## 读书笔记 * [创建型模式](http://jennica.space/2016/12/28/design-patterns-creational/) * [结构型模式](http://jennica.space/2016/12/30/design-patterns-structural/) * [行为型模式](http://jennica.space/2017/01/03/design-patterns-behavioral/) ## C++版 [design-patterns-cpp](https://github.com/yogykwan/design-patterns-cpp) ================================================ FILE: abstract_factory.py ================================================ import abc class User: """class user""" class IUser: __metaclass__ = abc.ABCMeta @abc.abstractmethod def insert_user(self, user): """insert user""" @abc.abstractmethod def get_user(self): """get user""" class SqlserverUser(IUser): def insert_user(self, user): print "Insert user into Sqlserver" def get_user(self): print "Get user from Sqlserver" class AccessUser(IUser): def insert_user(self, user): print "Insert user into Access" def get_user(self): print "Get user from Access" class Department: """class department""" class IDepartment: __metaclass__ = abc.ABCMeta @abc.abstractmethod def insert_department(self, department): """insert department""" def get_department(self): """get department""" class SqlserverDepartment(IDepartment): def insert_department(self, department): print "Insert department into Sqlserver" def get_department(self): print "Get department from Sqlserver" class AccessDepartment(IDepartment): def insert_department(self, department): print "Insert department into Access" def get_department(self): print "Get department from Access" class IFactory: __metaclass__ = abc.ABCMeta @abc.abstractmethod def create_user(self): """create user""" @abc.abstractmethod def create_department(self): """create deparment""" class SqlserverFactory(IFactory): def create_user(self): return SqlserverUser() def create_department(self): return SqlserverDepartment() class AccessFactory(IFactory): def create_user(self): return AccessUser() def create_department(self): return AccessDepartment() if __name__ == "__main__": # use sqlserver to insert/get user/department i_factory = SqlserverFactory() i_user = i_factory.create_user() i_user.insert_user(User()) i_user.get_user() i_department = i_factory.create_department() i_department.insert_department(Department()) i_department.get_department() # use access to insert/get user/department i_factory = AccessFactory() # just replace SqlserverFactory with AccessFactory i_user = i_factory.create_user() i_user.insert_user(User()) i_user.get_user() i_department = i_factory.create_department() i_department.insert_department(Department()) i_department.get_department() ================================================ FILE: adapter.py ================================================ import abc class Player: __metaclass__ = abc.ABCMeta def __init__(self, n): self.name = n @abc.abstractmethod def attack(self): """attack""" @abc.abstractmethod def defense(self): """defense""" class Center(Player): def attack(self): print "center " + self.name + " attack" def defense(self): print "center " + self.name + " defense" class ForeignCenter: def __init__(self, n): self.name = n def gong(self): print "foreign center " + self.name + " attack" def shou(self): print "foreign center " + self.name + " defense" class Translator(Player): def __init__(self, n): Player.__init__(self, n) self.foreign_center = ForeignCenter(n) def attack(self): self.foreign_center.gong() def defense(self): self.foreign_center.shou() if __name__ == "__main__": # center attack/defense center = Center("Russell") center.attack() center.defense() # foreign center gong/shou through translator's attack/defense translator = Translator("YaoMing") translator.attack() translator.defense() ================================================ FILE: bridge.py ================================================ import abc class HandsetSoft: __metaclass__ = abc.ABCMeta @abc.abstractmethod def run(self): """soft run""" class HandsetGame(HandsetSoft): def run(self): print "run game" class HandsetAddressList(HandsetSoft): def run(self): print "run address list" class HandsetBrand: __metaclass__ = abc.ABCMeta def __init__(self, s): self.soft = s @abc.abstractmethod def run(self): """run""" class HandsetBrandM(HandsetBrand): def run(self): print "handset brand M : ", self.soft.run() class HandsetBrandN(HandsetBrand): def run(self): print "handset brand N : ", self.soft.run() if __name__ == "__main__": handset_brand_m = HandsetBrandM(HandsetGame()) handset_brand_m.run() handset_brand_m = HandsetBrandM(HandsetAddressList()) handset_brand_m.run() handset_brand_n = HandsetBrandN(HandsetGame()) handset_brand_n.run() handset_brand_n = HandsetBrandN(HandsetAddressList()) handset_brand_n.run() ================================================ FILE: builder.py ================================================ import abc class Pen: """class pen""" class Graphics: """class graphics""" class PersonBuilder: __metaclass__ = abc.ABCMeta def __init__(self, p, g): self.pen = p self.grahics = g @abc.abstractmethod def BuildHead(self): """build head""" @abc.abstractmethod def BuildBody(self): """build body""" class PersonThinBuilder(PersonBuilder): def BuildHead(self): print "build thin head" def BuildBody(self): print "build thin body" class PersonFatBuilder(PersonBuilder): def BuildHead(self): print "build fat head" def BuildBody(self): print "build fat body" class PersonDirector: def __init__(self, pb): self.person_builder = pb def create_person(self): self.person_builder.BuildHead() self.person_builder.BuildBody() if __name__ == "__main__": # build thin person person_builder = PersonThinBuilder(Pen(), Graphics()) director = PersonDirector(person_builder) director.create_person() # build fat person person_builder = PersonFatBuilder(Pen(), Graphics()) # only replace PersonThinBuilder with PersonFatBuilder director = PersonDirector(person_builder) director.create_person() ================================================ FILE: chain_of_responsibility.py ================================================ import abc class Request: def __init__(self, t, n): self.type = t self.number = n class Manager: __metaclass__ = abc.ABCMeta def __init__(self, n): self.name = n self.superior = None def set_superior(self, s): self.superior = s @abc.abstractmethod def request_applications(self, r): """resolve request""" class CommonManager(Manager): def request_applications(self, r): if r.type == "leave application" and r.number <= 2: print self.name + " : approve" else: self.superior.request_applications(r) class Majordomo(Manager): def request_applications(self, r): if r.type == "leave application" and r.number <= 5: print self.name + " : approve" else: self.superior.request_applications(r) class GeneralManager(Manager): def request_applications(self, r): if r.type == "leave application": print self.name + " : approve" elif r.type == "salary increase": if r.number <= 500: print self.name + " : approve" else: print self.name + " : not approve" if __name__ == "__main__": common_manager = CommonManager("JingLi") majordomo = Majordomo("ZongJian") general_manager = GeneralManager("ZongJingLi") common_manager.set_superior(majordomo) majordomo.set_superior(general_manager) request = Request("leave application", 4) common_manager.request_applications(request) request = Request("salary increase", 1000) common_manager.request_applications(request) ================================================ FILE: command.py ================================================ import abc class Barbecuer(object): def bake_mutton(self): print "bake mutton" def bake_chicken(self): print "bake chicken" class Command(object): __metaclass__ = abc.ABCMeta def __init__(self, r): self.receiver = r @abc.abstractmethod def execute_command(self): pass class BakeMuttonCommand(Command): def execute_command(self): self.receiver.bake_mutton() class BakeChickenCommand(Command): def execute_command(self): self.receiver.bake_chicken() class Waiter(object): def __init__(self): self.commands = [] def set_order(self, o): if isinstance(o, BakeChickenCommand): print "chicken sold out" else: print "add order: " + type(o).__name__ self.commands.append(o) def cancel_order(self, o): print "cancel order: " + type(o).__name__ self.commands.remove(o) def notify(self): for command in self.commands: command.execute_command() if __name__ == "__main__": barbecuer = Barbecuer() bake_mutton_command = BakeMuttonCommand(barbecuer) bake_chicken_command = BakeChickenCommand(barbecuer) waiter = Waiter() waiter.set_order(bake_mutton_command) waiter.set_order(bake_mutton_command) waiter.set_order(bake_chicken_command) waiter.notify() ================================================ FILE: composite.py ================================================ import abc class Company: __metaclass__ = abc.ABCMeta def __init__(self, n): self.name = n @abc.abstractmethod def add(self, c): """add""" @abc.abstractmethod def display(self, d): """display""" @abc.abstractmethod def line_of_duty(self): """duty line""" class HrDepartment(Company): def __init__(self, n): Company.__init__(self, n) def add(self, c): print "leaf can't add component" def display(self, d): print "--" * d + self.name def line_of_duty(self): print self.name + " : human resources" class FinanceDepartment(Company): def __init__(self, n): Company.__init__(self, n) def add(self, c): print "leaf can't add component" def display(self, d): print "--" * d + self.name def line_of_duty(self): print self.name + " : finance analysis" class ConcreteCompany(Company): def __init__(self, n): Company.__init__(self, n) self.companies = [] def add(self, c): self.companies.append(c) def display(self, d): print "--" * d + self.name for company in self.companies: company.display(d + 1) def line_of_duty(self): for company in self.companies: company.line_of_duty() if __name__ == "__main__": beijing_head_office = ConcreteCompany("Beijing Head Office") beijing_head_office.add(HrDepartment("Beijing HR")) beijing_head_office.add(FinanceDepartment("Beijing Finance")) huadong_branch_office = ConcreteCompany("Huadong Branch Office") huadong_branch_office.add(HrDepartment("Huadong HR")) huadong_branch_office.add(FinanceDepartment("Huadong Finance")) beijing_head_office.add(huadong_branch_office) nanjing_office = ConcreteCompany("Nanjing Office") nanjing_office.add(HrDepartment("Nanjing HR")) nanjing_office.add(FinanceDepartment("Nanjing Finance")) huadong_branch_office.add(nanjing_office) hangzhou_office = ConcreteCompany("Hangzhou Office") hangzhou_office.add(HrDepartment("Hangzhou HR")) hangzhou_office.add(FinanceDepartment("Hangzhou Finance")) huadong_branch_office.add(hangzhou_office) beijing_head_office.display(0) beijing_head_office.line_of_duty() ================================================ FILE: decorator.py ================================================ import abc class Person: def show(self): print "person" class Finery(Person): def __init__(self, c): self.component = c def show(self): """finery show""" class Tie(Finery): def show(self): print "tie ", self.component.show() class Suit(Finery): def show(self): print "suit ", self.component.show() class Shoes(Finery): def show(self): print "shoes ", self.component.show() if __name__ == "__main__": person = Person() tie = Tie(person) suit = Suit(tie) shoes = Shoes(suit) shoes.show() ================================================ FILE: facade.py ================================================ class Stock1: def buy(self): print "buy stock1" def sell(self): print "sell stock1" class Stock2: def buy(self): print "buy stock2" def sell(self): print "sell stock2" class Reality1: def buy(self): print "buy reality1" def sell(self): print "sell reality1" class Fund: def __init__(self): self.stock1 = Stock1() self.stock2 = Stock2() self.reality1 = Reality1() def buy(self): self.stock1.buy() self.stock2.buy() self.reality1.buy() def sell(self): self.stock1.sell() self.stock2.sell() self.reality1.sell() if __name__ == "__main__": fund = Fund() fund.buy() fund.sell() ================================================ FILE: factory_method.py ================================================ import abc class Leifeng: __metaclass__ = abc.ABCMeta @abc.abstractmethod def wash(self): """"wash""" @abc.abstractmethod def sweep(self): """sweep""" @abc.abstractmethod def buy_rice(self): """buy rice""" class Undergraduate(Leifeng): def wash(self): print "undergraduate wash" def sweep(self): print "undergraduate sweep" def buy_rice(self): print "undergraduate buy rice" class Volunteer(Leifeng): def wash(self): print "volunteer wash" def sweep(self): print "volunteer sweep" def buy_rice(self): print "volunteer buy rice" class IFactory: __metaclass__ = abc.ABCMeta @abc.abstractmethod def CreateLeifeng(self): """create class leifeng""" class UndergraduateFactory(IFactory): def CreateLeifeng(self): return Undergraduate() class VolunteerFactory(IFactory): def CreateLeifeng(self): return Volunteer() if __name__ == "__main__": # create undergraduate to sweep i_factory = UndergraduateFactory() leifeng = i_factory.CreateLeifeng() leifeng.sweep() # create volunteer to wash i_factory = VolunteerFactory() # just replace UndergraduateFactory with VolunteerFactory leifeng = i_factory.CreateLeifeng() leifeng.wash() ================================================ FILE: flyweight.py ================================================ import abc class User: def __init__(self, n): self.name = n class Website: __metaclass__ = abc.ABCMeta @abc.abstractmethod def use(self, u): """users use website""" class ConcreteWebsite(Website): def __init__(self, wn): self.website_name = wn def use(self, u): print u.name + " use " + self.website_name class WebsiteFactory: flyweights = {} def get_website_category(self, n): if self.flyweights.has_key(n) is False: self.flyweights[n] = ConcreteWebsite(n) return self.flyweights[n] def get_website_count(self): print len(self.flyweights.keys()) if __name__ == "__main__": website_factory = WebsiteFactory() alice = User("Alice") bob = User("Bob") website = website_factory.get_website_category("bbs") website.use(alice) website.use(bob) website_factory.get_website_count() website = website_factory.get_website_category("blog") website.use(alice) website.use(bob) website_factory.get_website_count() website = website_factory.get_website_category("bbs") website.use(alice) website.use(bob) website_factory.get_website_count() ================================================ FILE: interpreter.py ================================================ import abc class Context(object): def __init__(self, t): self.text = t class Expression(object): def interpret(self, c): text = c.text.split(' ') key = text[0] value = float(text[1]) c.text = ' '.join(text[2:]) self.execute(key, value) @abc.abstractmethod def execute(self, k, v): pass class Scale(Expression): def execute(self, k, v): scale_dic = {1: 'bass', 2: 'alto', 3: 'treble'} print scale_dic[v] + " ", class Note(Expression): def execute(self, k, v): print k + " ", class ExpressionFactory(object): @staticmethod def create_expression(t): type = "Scale" if t == 'O' else "Note" obj = globals()[type]() return obj if __name__ == "__main__": context = Context("O 2 E 0.5 G 0.5 A 3") while len(context.text): expression = ExpressionFactory.create_expression(context.text[0]) expression.interpret(context) ================================================ FILE: iterator.py ================================================ import abc class Aggregate: __metaclass__ = abc.ABCMeta @abc.abstractmethod def create_iterator(self): """create iterator""" class List(Aggregate): def __init__(self): self.items = [] def create_iterator(self): return ListIterator(self) def count(self): return len(self.items) def __setitem__(self, key, value): if key >= len(self.items): self.items.append(value) else: self.items[key] = value def __getitem__(self, i): return self.items[i] class Iterator: __metaclass__ = abc.ABCMeta @abc.abstractmethod def first_item(self): """""" @abc.abstractmethod def next_item(self): """""" @abc.abstractmethod def is_done(self): """""" @abc.abstractmethod def current_item(self): """""" class ListIterator(Iterator): def __init__(self, a): self.current = 0 self.aggregate = a def first_item(self): return self.aggregate[0] def next_item(self): result = None self.current += 1 if self.current < self.aggregate.count(): result = self.aggregate[self.current] return result def is_done(self): return self.current >= self.aggregate.count() def current_item(self): return self.aggregate[self.current] if __name__ == "__main__": list = List() list[0] = 1 list[1] = 2 list[2] = 3 list_iterator = list.create_iterator() print list_iterator.first_item() print list_iterator.current_item() print list_iterator.next_item() print list_iterator.next_item() print list_iterator.is_done() print list_iterator.next_item() print list_iterator.is_done() ================================================ FILE: mediator.py ================================================ import abc class Country(object): __metaclass__ = abc.ABCMeta def __init__(self, un): self.un = un def declare(self, m): self.un.declare(self, m) @abc.abstractmethod def get_message(self, m): pass class Usa(Country): def get_message(self, m): print "USA gets: \"" + m + "\"" class Iraq(Country): def get_message(self, m): print "Iraq gets: \"" + m + "\"" class UnitedNations: __metaclass__ = abc.ABCMeta @abc.abstractmethod def declare(self, c, m): pass class SecurityCouncil(UnitedNations): def __init__(self): self.usa = None self.iraq = None def declare(self, c, m): if c == self.usa: self.iraq.get_message(m) elif c == self.iraq: self.usa.get_message(m) else: print "err: SecurityCouncil/declare" if __name__ == "__main__": security_council = SecurityCouncil() usa = Usa(security_council) iraq = Iraq(security_council) security_council.usa = usa security_council.iraq = iraq usa.declare("Stop nuclear weapons") iraq.declare("No nuclear here") ================================================ FILE: memento.py ================================================ class StateMemento(object): def __init__(self, h, m): self.hp = h self.mp = m class GameRole(object): def __init__(self): self.hp = 100 self.mp = 100 def fight(self): self.hp = 0 self.mp = 0 def create_memento(self): return StateMemento(self.hp, self.mp) def recovery_state(self, m): self.hp = m.hp self.mp = m.mp def state_display(self): print str(self.hp) + " " + str(self.mp) class StateCaretaker(object): def __init__(self, m): self.__memento = m # .__memento ==> ._StateCaretaker__memento (Name Mangling) def get_memento(self): return self.__memento if __name__ == "__main__": game_role = GameRole() state_caretaker = StateCaretaker(game_role.create_memento()) game_role.state_display() game_role.fight() game_role.state_display() game_role.recovery_state(state_caretaker.get_memento()) game_role.state_display() ================================================ FILE: observer.py ================================================ import abc class Observer: __metaclass__ = abc.ABCMeta def __init__(self, n, nr): self.name = n self.notifier = nr @abc.abstractmethod def update(self): """updated by notifier""" class NbaObserver(Observer): def update(self): print self.name + ", " + self.notifier.state + ", close NBA" class StockObserver(Observer): def update(self): print self.name + ", " + self.notifier.state + ", close stock" class Notifier: def __init__(self): self.observers = [] self.state = "" def attach(self, o): self.observers.append(o) def detach(self, o): self.observers.remove(o) def notify(self): for observer in self.observers: observer.update() class Boss(Notifier): pass class Secretary(Notifier): pass if __name__ == "__main__": boss = Boss() nba_observer = NbaObserver("Bob", boss) boss.attach(nba_observer) stock_observer = StockObserver("Alice", boss) boss.attach(stock_observer) boss.state = "boss's back himself" boss.notify() ================================================ FILE: prototype.py ================================================ import copy class WorkExperience: def __init__(self): self.company = "" self.time_area = "" class Resume: def __init__(self, n): self.name = n self.work_experience = WorkExperience() def set_personal_info(self, s, a): self.sex = s self.age = a def set_work_experience(self, c, ta): self.work_experience.company = c self.work_experience.time_area = ta def print_resume(self): print self.name + ", " + self.sex + ", " + self.age + ", " \ + self.work_experience.company + " : " + self.work_experience.time_area def clone(self): new_resume = copy.deepcopy(self) new_resume.work_experience = copy.deepcopy(self.work_experience) return new_resume if __name__ == "__main__": resume1 = Resume("Bob") resume1.set_personal_info("M", "24") resume1.set_work_experience("Google", "2015") resume2 = resume1 resume2.set_personal_info("F", "22") resume2.set_work_experience("Twitter", "2015") resume1.print_resume() resume2.print_resume() resume1 = Resume("Bob") resume1.set_personal_info("M", "24") resume1.set_work_experience("Google", "2015") resume2 = copy.copy(resume1) resume2.set_personal_info("F", "22") resume2.set_work_experience("Twitter", "2015") resume1.print_resume() resume2.print_resume() resume1 = Resume("Bob") resume1.set_personal_info("M", "24") resume1.set_work_experience("Google", "2015") resume2 = copy.deepcopy(resume1) resume2.set_personal_info("F", "22") resume2.set_work_experience("Twitter", "2015") resume1.print_resume() resume2.print_resume() resume1 = Resume("Bob") resume1.set_personal_info("M", "24") resume1.set_work_experience("Google", "2015") resume2 = resume1.clone() resume2.set_personal_info("F", "22") resume2.set_work_experience("Twitter", "2015") resume1.print_resume() resume2.print_resume() ================================================ FILE: proxy.py ================================================ import abc class GiveGift: __metaclass__ = abc.ABCMeta @abc.abstractmethod def __init__(self, sg): """init""" @abc.abstractmethod def give_dolls(self): """give dolls""" @abc.abstractmethod def give_flowers(self): """give flowers""" class SchoolGirl: def __init__(self, n): self.name = n class Pursuit(GiveGift): def __init__(self, sg): GiveGift.__init__(self, sg) self.school_girl = sg def give_dolls(self): print "give " + self.school_girl.name + " dolls" def give_flowers(self): print "give " + self.school_girl.name + " flowers" class Proxy(GiveGift): def __init__(self, sg): GiveGift.__init__(self, sg) self.pursuit = Pursuit(sg) def give_dolls(self): self.pursuit.give_dolls() def give_flowers(self): self.pursuit.give_flowers() if __name__ == "__main__": school_girl = SchoolGirl("Alice") proxy = Proxy(school_girl) proxy.give_flowers() proxy.give_dolls() ================================================ FILE: singleton.py ================================================ import threading class Singleton(object): instance = None lock = threading.RLock() @classmethod def __new__(cls): if cls.instance is None: cls.lock.acquire() if cls.instance is None: cls.instance = super(Singleton, cls).__new__(cls) cls.lock.release() return cls.instance if __name__ == "__main__": instance1 = Singleton() instance2 = Singleton() print id(instance1) == id(instance2) ================================================ FILE: state.py ================================================ import abc class Work: def __init__(self, h, f): self.hour = h self.finished = f self.state = WorkingState() def set_state(self, s): self.state = s def write_program(self): self.state.write_program(self) class State: __metaclass__ = abc.ABCMeta @abc.abstractmethod def write_program(self, w): """write program according to workstate""" class RestState(State): def write_program(self, w): print str(w.hour) + " : return to rest" class SleepingState(State): def write_program(self, w): print str(w.hour)+ " : sleeping" class OvertimeState(State): def write_program(self, w): if w.finished is True: w.set_state(RestState()) w.write_program() elif w.hour < 21: print str(w.hour) + " : overtime" else: w.set_state(SleepingState()) w.write_program() class WorkingState(State): def write_program(self, w): if w.hour < 17: print str(w.hour) + " : working" else: w.set_state(OvertimeState()) w.write_program() if __name__ == "__main__": work = Work(15, False) work.write_program() work = Work(20, False) work.write_program() work = Work(22, False) work.write_program() work = Work(20, True) work.write_program() ================================================ FILE: strategy.py ================================================ import abc class CashSuper: __metaclass__ = abc.ABCMeta @abc.abstractmethod def accept_cash(self, c): """caculate cash""" class CashNormal(CashSuper): def accept_cash(self, c): return c class CashRebate(CashSuper): def __init__(self, r): self.rebate = r def accept_cash(self, c): return c * self.rebate class CashReturn(CashSuper): def __init__(self, c, r): self.condition = c self.money = r def accept_cash(self, c): return c - int(c / self.condition) * self.money class CashContext: def __init__(self, t, s): self.cash = None if t == "normal": self.cash = CashNormal() elif t == "rebate": self.cash = CashRebate(float(s)) elif t == "return": args = s.split(' ') self.cash = CashReturn(float(args[0]), float(args[1])) def get_result(self, c): return self.cash.accept_cash(c) if __name__ == "__main__": cash_context = CashContext("normal", "") print cash_context.get_result(1000) cash_context = CashContext("rebate", "0.8") print cash_context.get_result(1000) cash_context = CashContext("return", "300 100") print cash_context.get_result(1000) ================================================ FILE: template_method.py ================================================ import abc class ExamPaper(object): __metaclass__ = abc.ABCMeta def question1(self): print "question1: " + self.answer1() @abc.abstractmethod def answer1(self): return "" def question2(self): print "question2: " + self.answer2() @abc.abstractmethod def answer2(self): return "" def question3(self): print "question3: " + self.answer3() @abc.abstractmethod def answer3(self): return "" class ExamPaperA(ExamPaper): def answer1(self): return "a" def answer2(self): return "a" def answer3(self): return "b" class ExamPaperB(ExamPaper): def answer1(self): return "b" def answer2(self): return "b" def answer3(self): return "c" if __name__ == "__main__": test_paper = ExamPaperA() print "Paper A:" test_paper.question1() test_paper.question2() test_paper.question3() print "Paper B:" test_paper = ExamPaperB() test_paper.question1() test_paper.question2() test_paper.question3() ================================================ FILE: visitor.py ================================================ import abc class Action(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def get_man_conclusion(self, p): pass @abc.abstractmethod def get_woman_conclusion(self, p): pass class Success(Action): def get_man_conclusion(self, p): print "man success" def get_woman_conclusion(self, p): print "woman success" class Failure(Action): def get_man_conclusion(self, p): print "man failure" def get_woman_conclusion(self, p): print "woman failure" class Person(object): __metaclass__ = abc.ABCMeta @abc.abstractmethod def accept(self, a): pass class Man(Person): def accept(self, a): a.get_man_conclusion(self) class Woman(Person): def accept(self, a): a.get_woman_conclusion(self) class ObjectStructure(object): def __init__(self): self.people = [] def attach(self, p): self.people.append(p) def detach(self, p): self.people.remove(p) def display(self, a): for person in self.people: person.accept(a) if __name__ == "__main__": man = Man() woman = Woman() object_structure = ObjectStructure() object_structure.attach(man) object_structure.attach(woman) object_structure.display(Success()) object_structure.display(Failure())