1. 抽象工厂模式
- import random
- class PetShop(object):
- def __init__(self,animal_factory=None):
- # pet 宠物 factory 工厂
- self.pet_factory = animal_factory
- def show_pet(self):
- pet = self.pet_factory.get_pet()
- print("this is a lovely", pet)
- print("it says",pet.speak())
- print("it eats",self.pet_factory.get_food())
- class Dog:
- def speak(self):
- return "Dog"
- def __str__(self):
- return "this is Dog"
- class Cat:
- def speak(self):
- return "Cat"
- def __str__(self):
- return "this is Cat"
- class CatFactory:
- def get_pet(self):
- return Cat()
- def get_food(self):
- return "cat food"
- class DogFactory:
- def get_pet(self):
- return Dog()
- def get_food(self):
- return "dog food"
- def get_factory():
- return random.choice([DogFactory,CatFactory])
- if __name__ == '__main__':
- shop = PetShop() # pet_factory 默认为 None, 后面延迟加载
- shop.pet_factory = get_factory()() # 延迟加载, 随机选择一个工厂然后实例出来一个对象给商店
- shop.show_pet()
2. 适配器模式
- import os
- class Dog:
- def __init__(self):
- self.name ="Dog"
- def bark(self): # bark : 叫声
- return "woof!" # woof 低吠声
- class Cat:
- def __init__(self):
- self.name = "Cat"
- def meow(self): # meow 猫叫声
- return "meow" # meow 猫叫声
- class Human:
- def __init__(self):
- self.name = "Human"
- def speak(self):
- return "hello, python"
- class Car:
- def __init__(self):
- self.name = "Car"
- def make_noise(self, noise_level):
- return "noise level is {}".format(noise_level)
- class Adapter: # adapter 适配器
- def __init__(self,obj,adapted_methods): # adpted 适应
- self.obj = obj
- self.__dict__.update(adapted_methods) # self.__dict__是打印对象所有的属性, 结果是一个字典 {"kye":value}
- # key 对应对象的属性, value 对应属性的属性值. 这里就相当于把不同类的方法都绑定到 Adapter 这个类实例化出来的
- # 对象的 make_noise 属性上面去, 该属性的值对应其他类里面的方法.
- def __getattr__(self, attr): # 当调用类不存的属性或者方法时, 就会触发该魔法方法
- return getattr(self.obj, attr) # getattr(object,attr [,default])
- def main():
- objects = []
- dog = Dog()
- objects.append(Adapter(dog,dict(make_noise=dog.bark)))
- cat = Cat()
- objects.append(Adapter(cat,dict(make_noise=cat.meow)))
- human = Human()
- objects.append(Adapter(human,dict(make_noise=human.speak)))
- car = Car()
- car_noise = lambda : car.make_noise(3)
- objects.append(Adapter(car,dict(make_noise=car_noise)))
- for obj in objects:
- print("A",obj.name,"goes",obj.make_noise()) # 这里 obj.make_noise 就相当于 dog.bark 这些方法, 后面加括号代表执行
- print(obj.obj) # 原来的对象被存储到 obj 属性里面.
- if __name__ == '__main__':
- # 适配器模式在不改变原有类的基础上, 统一了所有的方法, 还能够保存原有对象的引用 obj 属性
- main()
3. 共享模式
- class Borg:
- __shared_state = {}
- def __init__(self):
- self.state = None # 设置默认值防止报错
- self.__dict__ = self.__shared_state # 等号, 浅拷贝, 拷贝引用,
- # 后面实例化的对象的__dict__都是这个字典 __shared_state
- # 因为__shared_state 是类属性, 所以只有一份, 所有的实例对象共用
- def __str__(self): # 打印对象的时候自动执行的魔法方法
- return self.state # self.state 动态添加
- class YourBorg(Borg):
- def hhh(self):
- print(self.__shared_state)
- pass
- if __name__ == '__main__':
- rm1 = Borg()
- rm2 = Borg()
- rm1.state = "Done"
- print("rm1.state:", rm1) # rm1.state: Done
- print("rm1.state:", rm2) # rm2.state: Done
- rm2.state = "Running"
- print("rm1.state:", rm1) # rm1.state: Running
- print("rm2.state:", rm2) # rm2.state: Running
- print("rm1 id:", id(rm1)) # rm1 id: 41601008
- print("rm2 id:", id(rm2)) # rm2 id: 41601064
- rm3 = YourBorg() # 继承父类的__init__方法, 但是私有属性没有继承. 初始化的时候调用了父类的初始化方法
- # 下面 2 句注释证明上述观点
- # rm3.hhh()
- # print(rm3.__shared_state)
- print("rm3.state:", rm3) # rm3.state: Running
- # 共享模式通过私有一个类属性, 然后使用__dict__魔法方法共享所有的属性
- # 如果通过类属性共享属性, 那么每有一个需要共享的属性就需要新建一个类属性
4. 桥接模式
- class DrawingAPI1:
- def draw_circle(self, x, y, radius):
- print("API1.circle at {} : {} ,radius:{}".format(x, y, radius))
- class DrawingAPI2:
- def draw_circle(self,x,y,radius):
- print("API2.cirle at {} : {} ,radius:{}".format(x, y, radius))
- class CircleShape:
- def __init__(self,x,y,radius,drawing_api):
- self._x = x
- self._y = y
- self._radius = radius
- self._drawing_api = drawing_api
- def draw(self):
- self._drawing_api.draw_circle(self._x,self._y,self._radius)
- def scale(self,pct): # scale 规模
- self._radius *= pct # pct 百分比
- def main():
- shapes = (
- CircleShape(1,2,3,DrawingAPI1()),
- CircleShape(5,7,11,DrawingAPI2()),
- ) # 提供 2 个
- for shape in shapes:
- shape.scale(2.5)
- shape.draw()
- if __name__ == '__main__':
- # 桥接模式就是一个类的属性的值是另一个类的实例对象. 然后可以通过这个类的实例对象去调用另外一个类对象的方法
- main()
5. 建造者模式
- class Director: # director 监视
- def __init__(self):
- self.builder = None # builder 建造者
- def construct_building(self):
- self.builder.new_building()
- self.builder.build_floor()
- self.builder.build_size()
- def get_building(self):
- return self.builder.building
- class Builder:
- def __init__(self):
- self.building = None
- def new_building(self):
- self.building = Building()
- class Building:
- def __init__(self):
- self.floor = None
- self.size = None
- def __repr__(self): # 和__str__ 魔法方法类似, 都是打印对象的时候调用, 不过 repr 更强大
- # repr 方法在交互式环境下也能起作用, 即交互式环境直接输变量名打印的时候
- # __str__ 只有在 print 的时候才会触发
- return "Floor:%s | Size: %s" % (self.floor,self.size)
- class BuilderHouse(Builder):
- def build_floor(self):
- self.building.floor = "One"
- def build_size(self):
- self.building.size = "Big"
- class BuilderFlat(Builder): # flat 公寓
- def build_floor(self):
- self.building.floor = "More than One"
- def build_size(self):
- self.building.size = "small"
- if __name__ == '__main__':
- director = Director()
- director.builder = BuilderHouse()
- director.construct_building()
- building = director.get_building()
- print(building)
- director.builder = BuilderFlat()
- director.construct_building()
- building = director.get_building()
- print(building)
6. 职责链模式
- class Handler:
- def __init__(self):
- self.successor = None
- def add_successor(self,successor): # successor 后续的事, 继承者
- self.successor = successor
- class ConcreteHandler1(Handler):
- def handle(self,request):
- if request>0 and request<=10:
- print("concreteHandler1 deal %s"%request)
- elif self.successor is not None:
- self.successor.handle(request)
- else:
- print("no handler can deal with %s"%request)
- class ConcreteHandler2(Handler):
- def handle(self,request):
- if request>10 and request<=20:
- print("ConcreteHandler2 deal %s"%request)
- elif self.successor is not None:
- self.successor.handle(request)
- else:
- print("no handler can deal with %s" % request)
- class ConcreteHandler3(Handler):
- def handle(self,request):
- if request>20 and request<=30:
- print("ConcreteHandler3 deal %s"%request)
- elif self.successor is not None:
- self.successor.handle(request)
- else:
- print("no handler can deal with %s" % request)
- if __name__ == '__main__':
- h1 = ConcreteHandler1() # 创建处理者 1
- h2 = ConcreteHandler2() # 创建处理者 2
- h3 = ConcreteHandler3() # 创建处理者 3
- h1.add_successor(h2) # 添加 h1 如果处理不了就让 h2 去处理
- h2.add_successor(h3) # 如果 h2 处理不了就让 h3 去处理
- requests = [1,3,23,42,34,67,11,22,14,36]
- for request in requests:
- h1.handle(request)
7. 命令模式
- import os
- class MoveFileCommand(object):
- def __init__(self,src,dest):
- self.src = src
- self.dest = dest
- def execute(self):
- self() # 直接调用对象本身会执行__call__方法
- def __call__(self, *args, **kwargs): # __call__ 魔法方法直接调用对象的时候执行的方法
- print("renaming {} to {}".format(self.src,self.dest))
- os.rename(self.src,self.dest)
- def undo(self):
- print("renaming {} to {}".format(self.dest,self.src))
- os.rename(self.dest,self.src)
- if __name__ == '__main__':
- command_stack = []
- command_stack.append(MoveFileCommand("foo.txt","bar.txt"))
- command_stack.append(MoveFileCommand("bar.txt","foo.txt"))
- for cmd in command_stack:
- cmd.execute()
- for cmd in reversed(command_stack):
- cmd.undo()
8. 装饰器模式
- class foo(object):
- def f1(self):
- print("func f1")
- def f2(self):
- print("func f2")
- class foo_decorator(object):
- def __init__(self,decorator):
- self._decorator = decorator
- def f1(self):
- print("decorator f1")
- self._decorator.f1()
- def __getattr__(self, item):
- # 当得不到想要的属性时, 就去自己的装饰里面拿, 使用 getattr() 内建方法
- return getattr(self._decorator,item)
- if __name__ == '__main__':
- # 主要思想还是使用魔法方法 __getattr__ 方法, 然后把另外一个对象赋值到自身的属性上面.
- # 添加一个运行另外一个对象的接口, 没有接口时, 就去直接调用另一个对象的方法.
- u = foo()
- d = foo_decorator(u)
- d.f1()
- d.f2()
9. 外观模式
- class small_or_piece1:
- def __init__(self):
- pass
- def do_small1(self):
- print('do small 1')
- class small_or_piece_2:
- def __init__(self):
- pass
- def do_small2(self):
- print('do small 2')
- class small_or_piece_3:
- def __init__(self):
- pass
- def do_small3(self):
- print('do small 3')
- class outside:
- def __init__(self):
- self.__small1 = small_or_piece1()
- self.__small2 = small_or_piece_2()
- self.__small3 = small_or_piece_3()
- def method1(self):
- self.__small1.do_small1() ## 如果这里调用的不只 2 两函数, 作用就显示出来了, 可以把原本复杂的函数调用关系清楚化, 统一化
- self.__small2.do_small2()
- def method2(self):
- self.__small2.do_small2()
- self.__small3.do_small3()
- if __name__ == '__main__':
- # 外观模式应用于在很多复杂而小功能需要调用时, 并且这些调用还具有一定的相关性, 即一调用就是一系列的调用.
- osd = outside()
- osd.method1()
- osd.method2()
10. 单例模式
- class A(object):
- __obj = False
- __init = False
- def __init__(self, name):
- if not A.__init:
- self.name = name
- A.__init = True
- def __new__(cls, *args, **kwargs):
- if not A.__obj:
- A.__obj = super().__new__(cls)
- return A.__obj
- if __name__ == '__main__':
- # 只初始化一次的单例模式
- a = A("nick")
- b = A("nick2")
- print(a.name) # nick
- print(b.name) # nick
- print(a == b) # True
- print(id(a), id(b)) # 54527760 54527760
11. 图搜索模式
- class GraphSearch:
- def __init__(self, graph):
- self.graph = graph
- def find_path(self, start, end, path=None):
- self.start = start
- self.end = end
- if not path:
- self.path = []
- self.path.extend([self.start])
- if self.start not in self.graph:
- return None # 如果图里面没有这个 start 这个 key, 说明这条路不同, 返回 None
- if self.start == self.end:
- return self.path
- for node in self.graph[self.start]:
- if node not in self.path:
- newpath = self.find_path(node, self.end, self.path)
- if newpath: # newpath 不存在的时候说明这条路没有走通, 继续循环, 走下一条路
- return newpath
- return None # 如果上面一直没有 return, 走到这里说明从 start 没有找到 end. 返回 None
- # def find_all_path(self, start, end, path=None, run_num=[]):
- # self.start = start
- # self.end = end
- # if not path:
- # self.path = []
- # self.path.extend([self.start])
- # paths = []
- # if self.start not in self.graph:
- # return []
- # if self.start == self.end:
- # if len(run_num) == 0:
- # paths.append([self.start])
- # else:
- # return [self.path]
- # for node in self.graph[self.start]:
- # if node not in self.path:
- # run_num.append(1)
- # newpaths = self.find_all_path(node, self.end, self.path)
- # for newpath in newpaths:
- # paths.append(newpath)
- # return paths
- def find_all_path(self, start, end, path=None):
- self.start = start
- self.end = end
- if not path:
- self.path = []
- self.path += [self.start]
- if self.start == self.end:
- return [self.path]
- if self.start not in self.graph:
- return []
- paths = []
- for node in self.graph[self.start]:
- if node not in self.path:
- newpaths = self.find_all_path(node, self.end, self.path)
- for newpath in newpaths:
- paths.append(newpath)
- return paths
- def find_shortest_path(self, start, end, path=None):
- self.start = start
- self.end = end
- if not path:
- self.path = []
- self.path.extend(self.start)
- if self.start not in self.graph:
- return None
- if self.start == self.end:
- return self.path
- shortpath = None
- for node in self.graph[self.start]:
- if node not in self.path:
- newpath = self.find_shortest_path(node, self.end, self.path)
- if newpath:
- if not shortpath or len(newpath) < len(shortpath):
- shortpath = newpath
- return shortpath
- graph = {
- "A": ["B", "C"],
- 'B': ['C', 'D'],
- 'C': ['D'],
- 'D': ['A'],
- 'E': ['F'],
- 'F': ['C']
- }
- graph1 = GraphSearch(graph)
- print(graph1.find_path("A","D"))
- print(graph1.find_all_path("A","A"))
- print(graph1.find_all_path("A","D"))
- print(graph1.find_shortest_path("A","D"))
来源: http://www.jianshu.com/p/34748ab46088