目录
4.职责链模式(Chain of Responsibility)
1.观察者模式(Observer) #典型的发布订阅
意图:
- 多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式
适用性:
- 当一个对象的改变需要同时改变其它对象, 而不知道具体有多少对象有待改变。
- 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之, 你不希望这些对象是紧密耦合的
基本思想:
具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则
观察者模式的主要角色如下。
- 抽象主题(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
- 具体主题(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
- 抽象观察者(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
- 具体观察者(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
'''observer model'''
#当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
#observer-->observerbase.attach
# -->observer.msg-->observerbase.notify-->view.update
class ObserverBase(object):
def __init__(self):
self._observer_list=[]
def attach(self,observer_subject):
if observer_subject not in self._observer_list:
self._observer_list.append(observer_subject)
print('[%s]已经将[%s]加入观察者队列'%(self.name,observer_subject))
def detach(self,observer_subject):
try:
self._observer_list.remove(observer_subject)
print('不在观察[%s]'%observer_subject)
except ValueError:
pass
def notify(self):
for objserver in self._observer_list:
objserver.update(self)
class Observer(ObserverBase):
def __init__(self,name):
super(Observer,self).__init__()
self.name=name
self._msg=''
#@property装饰器,把get方法变为属性
@property
def msg(self):
return self._msg
#@score.setter,负责把set方法变成给属性赋值
@msg.setter
def msg(self,content):
self._msg=content
self.notify()
class Viewed1(object):
def update(self,observer_subject):
print('View1:收到[%s]消息[%s]'%(observer_subject.name,observer_subject.msg))
class Viewed2(object):
def update(self,observer_subject):
print('View2:收到[%s]消息[%s]'%(observer_subject.name,observer_subject.msg))
def observer_model():
observer1=Observer('View1放哨者')
observer2=Observer('View2放哨者')
view1=Viewed1()
view2=Viewed2()
observer1.attach(view1)
observer1.attach(view2)
observer2.attach(view1)
observer2.attach(view2)
observer1.msg='敌人来了'
observer2.msg='发现敌人,请紧急撤离'
if __name__=="__main__":
observer_model()
2.*状态模式(State)
定义:
- 对有状态的对象,把复杂的“判断逻辑”提取到不同的状态对象中,
- 允许状态对象在其内部状态发生改变时改变其行为。
适用性:
状态模式是一种对象行为型模式
- 状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”
- 有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
基本思想:
状态模式包含以下主要角色。
- 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
- 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
- 具体状态(Concrete State)角色:实现抽象状态所对应的行为。
'''难state model'''
# 一个对象能在运行时刻根据状态改变它的行为
# 通过一个对象的方法调用已经存在其他类对象的状态
class State(object):
def scan(self):
self.pos+=1
if self.pos==len(self.stations):
self.pos=0
print('Scanning... Station is',self.stations)
class AmState(State):
def __init__(self,radio):
self.radio=radio
self.stations=['1250','1380','1510']
self.pos=0
self.name='AM'
def toggle_amfm(self):
print('Switching to FM')
self.radio.state=self.radio.fmstate
class FmState(State):
def __init__(self,radio):
self.radio=radio
self.stations=['111','222','333']
self.pos=0
self.name='FM'
def toggle_amfm(self):
print("Switching to AM")
self.radio.state = self.radio.amstate
#包括一个scan按钮, 和AM/FM转换的开关的
class Radio(object):
def __init__(self):
self.amstate=AmState(self)
self.fmstate=FmState(self)
self.state=self.amstate
def toggle_amfm(self):
self.state.toggle_amfm()
def scan(self):
self.state.scan()
def state_model():
radio=Radio()
#
actions=[radio.scan] * 2+[radio.toggle_amfm]+ [radio.scan] * 2
actions=actions * 2
for action in actions:
action()
if __name__=="__main__":
state_model()
3.策略模式(Strategy)
定义:
- 该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
- 把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。
适用性:
- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句
- 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
- 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。
基本思想:
策略模式的主要角色如下。
- 抽象策略(Strategy)类:定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,环境角色使用这个接口调用不同的算法,一般使用接口或抽象类实现。
- 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现。
- 环境(Context)类:持有一个策略类的引用,最终给客户端调用。
'''strategy model'''
#类似于facade model
class TravelStrategy(object):
def travelAlgorithm(self):
pass
class AirplaneStrategy(TravelStrategy):
def travelAlgorithm(self):
print('坐飞机出行...')
class TrainStrategy(TravelStrategy):
def travelAlgorithm(self):
print('坐高铁出行...')
class CarStrategy(TravelStrategy):
def travelAlgorithm(self):
print('坐汽车出行...')
class TravelInterface(object):
# 1.第一次使用要初始化
def __init__(self,travel_strategy):
self.travel_strategy=travel_strategy
# 2.更改算法
def set_strategy(self,travel_strategy):
self.travel_strategy=travel_strategy
def travel(self):
return self.travel_strategy.travelAlgorithm()
def strategy_model():
travel=TravelInterface(AirplaneStrategy())
travel.travel()
travel.set_strategy(CarStrategy())
travel.travel()
if __name__=="__main__":
strategy_model()
4.职责链模式(Chain of Responsibility)
意图:
- 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
适用性:
- 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
- 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
基本思想:
职责链模式主要包含以下角色。
- 抽象处理者(Handler)角色:定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
- 具体处理者(Concrete Handler)角色:实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理请求则处理,否则将该请求转给它的后继者。
- 客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
'''Chain of Responsibility'''
#对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
class BaseHandeler(object):
def seccessor(self,successor):
self._successor=successor
class RequestHandler1(BaseHandeler):
name='TeamLeader'
def handle(self,request):
if request<500:
print('审批者[%s],请求金额[%s],审批结果[审批通过]'%(self.name,request))
else:
print('[%s]无权审批,交给下一个审批者'%self.name)
# 不可缺
self._successor.handle(request)
class RequestHandler2(BaseHandeler):
name='DeptManager'
def handle(self,request):
if request<5000:
print('审批者[%s],请求金额[%s],审批结果[审批通过]'%(self.name,request))
else:
print('[%s]无权审批,交给下一个审批者'%self.name)
# 不可缺
self._successor.handle(request)
class RequestHandler3(BaseHandeler):
name='CEO'
def handle(self,request):
if request<10000:
print('审批者[%s],请求金额[%s],审批结果[审批通过]'%(self.name,request))
else:
print('[%s]超出预算,不予批准'%self.name)
class RequestAPI(object):
h1=RequestHandler1()
h2=RequestHandler2()
h3=RequestHandler3()
h1.seccessor(h2)
h2.seccessor(h3)
def __init__(self,name,amount):
self.name=name
self.amount=amount
def handle(self):
self.h1.handle(self.amount)
def cor_model():
r1=RequestAPI('Alarm',8000)
r1.handle()
print(r1.__dir__)
if __name__=="__main__":
cor_model()
5.*命令模式(Command)
意图:
- 将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通,这样方便将命令对象进行储存、传递、调用、增加与管理
适用性:
- 增加或删除命令非常方便。采用命令模式增加与删除命令不会影响其他类,它满足“开闭原则”,对扩展比较灵活。
- 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
- 方便实现 Undo 和 Redo 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复
基本思想:
命令模式包含以下主要角色。
- 抽象命令类(Command)角色:声明执行命令的接口,拥有执行命令的抽象方法 execute()。
- 具体命令角色(Concrete Command)角色:是抽象命令类的具体实现类,它拥有接收者对象,并通过调用接收者的功能来完成命令要执行的操作。
- 实现者/接收者(Receiver)角色:执行命令功能的相关操作,是具体命令对象业务的真正实现者。
- 调用者/请求者(Invoker)角色:是请求的发送者,它通常拥有很多的命令对象,并通过访问命令对象来执行相关请求,它不直接访问接收者。
'''command model'''
#将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化
#对请求排队或记录请求日志,以及支持可撤消的操作
class FileCommand(object):
def __init__(self,old_name,new_name):
self._old_name=old_name
self._new_name=new_name
def execute(self):
#?
self()
def __call__(self):
print('renaming{}to{}'.format(self._old_name,self._new_name))
os.rename(self._old_name,self._new_name)
def undo(self):
print()
print('renaming{}to{}'.format(self._new_name,self._old_name))
os.rename(self._new_name,self._old_name )
def command_model():
command_stack=[]
command_stack.append(FileCommand('newFile1.txt','oldFile1.txt'))
command_stack.append(FileCommand('newFile2.txt','oldFile2.txt'))
for cmd in command_stack:
cmd.execute()
for cmd in command_stack:
cmd.undo()
if __name__=="__main__":
command_model()
6.*访问者模式(Visitor)
定义:
- 它将对数据的操作与数据结构进行分离。
- 将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。
适用性:
- 将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
基本思想:
访问者模式包含以下主要角色。
- 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
- 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
- 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
- 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
- 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
'''难visitor model'''
#定义一个操作中的算法的骨架,而将一些步骤延迟到子类中
#TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
class Node(object):
pass
class A(Node):
pass
class B(Node):
pass
class C(Node):
pass
class Visitor(object):
#*args 用来将参数打包成tuple给函数体调用
#**kwargs 打包关键字参数成dict给函数体调用
def visit(self,node,*args,**kwargs):
meth=None
#cls作为第一个参数用来表示类本身
for cls in node.__class__.__mro__:
meth_name='visit_'+cls.__name__
#getattr()函数用于返回一个对象属性值
#__mro__来表示方法解析顺序
meth=getattr(self,meth_name,None)
if meth:
break
if not meth:
meth=self.generic_visit
return meth(node,*args,**kwargs)
def generic_visit(self,node,*args,**kwargs):
print('generic_visit'+node.__class__.__name__)
def visit_B(self,node,*args,**kwargs):
print('visit_B'+node.__class__.__name__)
def visitor_model():
a=A()
b=B()
c=C()
visitor=Visitor()
visitor.visit(a)
visitor.visit(b)
visitor.visit(c)
if __name__=="__main__":
visitor_model()
7.*调停者模式(Mediator)
没有理解,希望有大佬可以帮忙解决一下
8.备忘录模式(Memento)
# 如:虚拟机快照
#(克隆:深copy、快照:浅copy)
定义:
- 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模式。
适用性:
- 必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态。
基本思想:
备忘录模式的主要角色如下。
- 发起人(Originator)角色:记录当前时刻的内部状态信息,提供创建备忘录和恢复备忘录数据的功能,实现其他业务功能,它可以访问备忘录里的所有信息。
- 备忘录(Memento)角色:负责存储发起人的内部状态,在需要的时候提供这些内部状态给发起人。
- 管理者(Caretaker)角色:对备忘录进行管理,提供保存与获取备忘录的功能,但其不能对备忘录的内容进行访问与修改。
'''memento'''
#必须保存一个对象在某一个时刻的(部分)状态, 这样以后需要时它才能恢复到先前的状态
def Memento(obj,deep=False):
state=(copy.copy,copy.deepcopy)[bool(deep)](obj.__dict__)
def Restore():
obj.__dict__.clear()
obj.__dict__.update(state)
return Restore
class Transaction:
deep=False
def __init__(self,*targets):
self.targets=targets
self.Commit()
def Commit(self):
self.states=[Memento(target,self.deep) for target in self.targets]
def Rollback(self):
for st in self.states:
st()
class transactional(object):
def __init__(self,method):
self.method=method
def __get__(self,obj,T):
def transaction(*args,**kwargs):
state=Memento(obj)
try:
return self.method(obj,*args,**kwargs)
except:
state()
raise
return transaction
class NumObj(object):
def __init__(self,value):
self.value=value
#_repr__() 是一个非常特殊的方法,它是一个“自我描述”的方法
def __repr__(self):
return '<%s:%r>'%(self.__class__.__name__,self.value)
def Increment(self):
self.value+=1
#?
@transactional
def DoStuff(self):
self.value=1111
self.Increment()
def memento_model():
n=NumObj(-1)
print(n)
print(n.__repr__())
t=Transaction(n)
print(t.targets)
print(t.states)
try:
for i in range(3):
n.Increment()
print(n)
#1.保存状态
t.Commit()
print('--commited')
for i in range(3):
n.Increment()
print(n)
#2.异常回滚
n.value+='x'
print(n)
except:
t.Rollback()
print('--rolled back')
print(n)
print('--now doing stuff--')
try:
n.DoStuff()
except:
print('->doing stuff failed')
#打印出当前具体的异常信息
traceback.print_exc(0)
print(n)
if __name__=="__main__":
memento_model()
9. 迭代器模式(Iterator)
定义:
- 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示
适用性:
- 访问一个聚合对象的内容而无须暴露它的内部表示。
- 遍历任务交由迭代器完成,这简化了聚合类。
- 增加新的聚合类和迭代器类都很方便,无须修改原有代码。
- 它支持以不同方式遍历一个聚合,甚至可以自定义迭代器的子类以支持新的遍历。
- 封装性良好,为遍历不同的聚合结构提供一个统一的接口。
基本思想:
迭代器模式主要包含以下角色。
- 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合对象以及创建迭代器对象的接口。
- 具体聚合(ConcreteAggregate)角色:实现抽象聚合类,返回一个具体迭代器的实例。
- 抽象迭代器(Iterator)角色:定义访问和遍历聚合元素的接口,通常包含 hasNext()、first()、next() 等方法。
- 具体迭代器(Concretelterator)角色:实现抽象迭代器接口中所定义的方法,完成对聚合对象的遍历,记录遍历的当前位置。
'''iterator model'''
#提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示
def count_to(count):
'''counts by word numbers, up to a maximum of five'''
numbers=['one','two','three','four','five']
# 打包为元组的列表
for pos, number in zip(range(count),numbers):
yield number
def iterator_model():
count_to_two=count_to(2)
count_to_five=count_to(5)
print('counting to two...')
for number in count_to_two:
print(number)
print('')
print('counting to five...')
for number in count_to_five:
print(number)
print('')
if __name__=="__main__":
iterator_model()
10. *解释器模式(Interpreter)
定义:
用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。
适用性:
不会啊,求大佬指教
基本思想:
不会啊,求大佬指教
'''interpreter model'''
#???这东西好像没啥用啊
class Context:
def __init__(self):
self.input='1'
self.output=''
class AbstractExpression:
def Interpret(self,context):
pass
class Expression(AbstractExpression):
def Interpret(self,context):
print('terminal interpret')
class NonterminalExpression(AbstractExpression):
def Interpret(self,context):
print('Nonterminal interpret')
def interpreter_model():
context=''
c=[]
c=c+[Expression()]
c=c+[NonterminalExpression()]
c=c+[Expression()]
c=c+[Expression()]
for a in c:
a.Interpret(context)
print(Context().input)
if __name__=="__main__":
interpreter_model()
11.*模板方法(Template Method)
# Factory Method 使一个类的实例化延迟到其子类
# Visitor Method 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现
定义:
定义一个操作中的算法骨架,而将算法的一些步骤延迟到子类中,使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤。
适用性:
它封装了不变部分,扩展可变部分。它把认为是不变部分的算法封装到父类中实现,而把可变部分算法由子类继承实现,便于子类继续扩展
基本思想:
- 抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。
这些方法的定义如下。
① 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
② 基本方法:是整个算法中的一个步骤,包含以下几种类型。
抽象方法:在抽象类中申明,由具体子类实现。
具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
- 具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤
实例1:
'''template model'''
#!一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
ingredients='banana eggs apple'
line='-'*10
# 1.Skeleton
def iter_elements(getter,action):
'''template skeleton that iterates items'''
for element in getter():
action(element)
print(line)
def rev_elements(getter,action):
for element in getter()[::-1]:
action(element)
print(line)
# 2.Getters
def get_list():
return ingredients.split()
def get_lists():
return [list(x) for x in ingredients.split()]
# 3.Action
def print_item(item):
print(item)
def reverse_item(item):
#?
print(item[::-1])
# 4.makes templates
def make_template(skeleton,getter,action):
def template():
#这里传入的参数skeleton是一个函数
skeleton(getter,action)
return template
# 5.create our template functions
templates=[make_template(s,g,a)
for s in(iter_elements,rev_elements)
for g in(get_list,get_lists)
for a in(print_item,reverse_item)
]
def template_meth1():
for template in templates:
template()
# print(iter_elements())
# print(rev_elements())
print('get_list()==========',get_list())
print('get_lists()==========',get_lists())
print('print_item==========',print_item)
print('reverse_item==========',reverse_item)
if __name__=="__main__":
template_meth1()
runfile('H:/WindowGUI/Model/BehaviorModel.py', wdir='H:/WindowGUI/Model')
banana
----------
eggs
----------
apple
----------
ananab
----------
sgge
----------
elppa
----------
['b', 'a', 'n', 'a', 'n', 'a']
----------
['e', 'g', 'g', 's']
----------
['a', 'p', 'p', 'l', 'e']
----------
['a', 'n', 'a', 'n', 'a', 'b']
----------
['s', 'g', 'g', 'e']
----------
['e', 'l', 'p', 'p', 'a']
----------
apple
----------
eggs
----------
banana
----------
elppa
----------
sgge
----------
ananab
----------
['a', 'p', 'p', 'l', 'e']
----------
['e', 'g', 'g', 's']
----------
['b', 'a', 'n', 'a', 'n', 'a']
----------
['e', 'l', 'p', 'p', 'a']
----------
['s', 'g', 'g', 'e']
----------
['a', 'n', 'a', 'n', 'a', 'b']
----------
get_list()========== ['banana', 'eggs', 'apple']
get_lists()========== [['b', 'a', 'n', 'a', 'n', 'a'], ['e', 'g', 'g', 's'], ['a', 'p', 'p', 'l', 'e']]
print_item========== <function print_item at 0x1C5438E8>
reverse_item========== <function reverse_item at 0x1C543930>
实例2:
class Register(object):
'''用户注册'''
def register(self):
pass
def login(self):
pass
def auth(self):
self.register()
self.login()
class RegisterByPhone(Register):
'''手机注册'''
def register(self):
print('===用手机注册===')
def login(self):
print('===用手机登录===')
class RegisterByWeiChat(Register):
def register(self):
print('===用微信注册===')
def login(self):
print('===用微信登录===')
def template_meth2():
register1=RegisterByPhone()
register1.login()
register2=RegisterByWeiChat()
register2.login()
if __name__=="__main__":
template_meth2()