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"))