Skip to content

Commit 6024b83

Browse files
committedOct 9, 2019
no message
1 parent 90e56cf commit 6024b83

7 files changed

+497
-0
lines changed
 

‎行为型模式-中介者模式.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:13
4+
5+
"""
6+
中介者模式(Mediator Pattern):用一个对象来封装一系列的对象交互,中介者使各对象不需要显示地相互引用,从而使耦合松散,而且可以独立地改变它们之间的交互.
7+
"""
8+
from monkey_print2 import print
9+
class ChatRoom:
10+
@staticmethod
11+
def show_message(user,msg):
12+
print(f'{user.name} 说: {msg}')
13+
14+
class User:
15+
def __init__(self,name):
16+
self.name = name
17+
18+
def send_msg(self,msg):
19+
ChatRoom.show_message(self,msg)
20+
21+
if __name__ == '__main__':
22+
user1 = User('小明')
23+
user2 = User('小红')
24+
user1.send_msg('早上好')
25+
user2.send_msg('晚上好')
26+
27+
"""
28+
"D:/coding2/python36patterns/行为型模式-中介者模式.py:12" 11:21:04 小明 说: 早上好
29+
"D:/coding2/python36patterns/行为型模式-中介者模式.py:12" 11:21:04 小红 说: 晚上好
30+
"""

‎行为型模式-发布订阅模式.py

+77
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,80 @@
11
# -*- coding: utf-8 -*-
22
# @Author : ydf
33
# @Time : 2019/10/9 0009 10:39
4+
5+
"""重要程度 ☆☆☆
6+
订阅-发布模式和观察者模式概念相似,但在订阅-发布模式中,订阅者和发布者之间多了一层中间件:一个被抽象出来的信息调度中心。
7+
8+
但其实没有必要太深究 2 者区别,因为《Head First 设计模式》这本经典书都写了:发布+订阅=观察者模式。其核心思想是状态改变和发布通知。在此基础上,根据语言特性,进行实现即可。
9+
10+
对比观察者模式看。23种经典设计模式里面不包括发布订阅设计模式,区别太小。
11+
"""
12+
13+
class Event:
14+
def __init__(self):
15+
self.client_list = {}
16+
17+
def listen(self, key, fn):
18+
if key not in self.client_list:
19+
self.client_list[key] = []
20+
self.client_list[key].append(fn)
21+
22+
def trigger(self, *args, **kwargs):
23+
fns = self.client_list[args[0]]
24+
25+
length = len(fns)
26+
if not fns or length == 0:
27+
return False
28+
29+
for fn in fns:
30+
fn(*args[1:], **kwargs)
31+
32+
return False
33+
34+
def remove(self, key, fn):
35+
if key not in self.client_list or not fn:
36+
return False
37+
38+
fns = self.client_list[key]
39+
length = len(fns)
40+
41+
for _fn in fns:
42+
if _fn == fn:
43+
fns.remove(_fn)
44+
45+
return True
46+
47+
48+
# 借助继承为对象安装 发布-订阅 功能
49+
class SalesOffice(Event):
50+
def __init__(self):
51+
super().__init__()
52+
53+
54+
# 根据自己需求定义一个函数:供事件处理完后调用
55+
def handle_event(event_name):
56+
def _handle_event(*args, **kwargs):
57+
print("Price is", *args, "at", event_name)
58+
59+
return _handle_event
60+
61+
62+
if __name__ == "__main__":
63+
# 创建2个回调函数
64+
fn1 = handle_event("event01")
65+
fn2 = handle_event("event02")
66+
67+
sales_office = SalesOffice()
68+
69+
# 订阅event01 和 event02 这2个事件,并且绑定相关的 完成后的函数
70+
sales_office.listen("event01", fn1)
71+
sales_office.listen("event02", fn2)
72+
73+
# 当两个事件完成时候,触发前几行绑定的相关函数
74+
sales_office.trigger("event01", 1000)
75+
sales_office.trigger("event02", 2000)
76+
77+
sales_office.remove("event01", fn1)
78+
79+
# 打印:False
80+
print(sales_office.trigger("event01", 1000))

‎行为型模式-备忘录模式.py

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:22
4+
5+
"""
6+
备忘录模式
7+
备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。备忘录模式属于行为型模式。
8+
9+
介绍
10+
意图:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
11+
12+
主要解决:所谓备忘录模式就是在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样可以在以后将对象恢复到原先保存的状态。
13+
14+
何时使用:很多时候我们总是需要记录一个对象的内部状态,这样做的目的就是为了允许用户取消不确定或者错误的操作,能够恢复到他原先的状态,使得他有"后悔药"可吃。
15+
16+
如何解决:通过一个备忘录类专门存储对象状态。
17+
18+
关键代码:客户不与备忘录类耦合,与备忘录管理类耦合。
19+
20+
应用实例: 1、后悔药。 2、打游戏时的存档。 3、Windows 里的 ctri + z。 4、IE 中的后退。 4、数据库的事务管理。
21+
22+
优点: 1、给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。 2、实现了信息的封装,使得用户不需要关心状态的保存细节。
23+
24+
缺点:消耗资源。如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存。
25+
26+
使用场景: 1、需要保存/恢复数据的相关状态场景。 2、提供一个可回滚的操作。
27+
28+
注意事项: 1、为了符合迪米特原则,还要增加一个管理备忘录的类。 2、为了节约内存,可使用原型模式+备忘录模式。
29+
"""
30+
from monkey_print2 import print
31+
#!/usr/bin/env python
32+
# -*- coding:utf-8 -*-
33+
34+
__author__ = 'Andy'
35+
"""
36+
大话设计模式
37+
设计模式——备忘录模式
38+
备忘录模式(Memento Pattern):不破坏封装性的前提下捕获一个对象的内部状态,并在该对象之外保存这个状态,这样已经后就可将该对象恢复到原先保存的状态
39+
"""
40+
from monkey_print2 import print
41+
# 发起人类
42+
class Originator(object):
43+
44+
def __init__(self, state):
45+
self.state = state
46+
47+
def create_memento(self):
48+
return Memento(self.state)
49+
50+
def set_memento(self, memento):
51+
self.state = memento.state
52+
53+
def show(self):
54+
print("当前状态 ", self.state)
55+
56+
# 备忘录类
57+
class Memento(object):
58+
59+
def __init__(self, state):
60+
self.state = state
61+
62+
# 管理者类
63+
class Caretaker(object):
64+
65+
def __init__(self,memento):
66+
self.memento = memento
67+
68+
69+
70+
if __name__ == "__main__":
71+
# 初始状态
72+
originator = Originator(state='On')
73+
originator.show()
74+
# 备忘录
75+
caretaker = Caretaker(originator.create_memento())
76+
# 修改状态
77+
originator.state = 'Off'
78+
originator.show()
79+
# 复原状态
80+
originator.set_memento(caretaker.memento)
81+
originator.show()

‎行为型模式-访问者模式.py

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:31
4+
5+
"""
6+
1。为什么要使用设计模式?
7+
从理论上来说,设计模式是对程序问题比较好的解决方案。无数的程序员都曾经遇到过这些问题,并且他们使用这些解决方案去处理这些问题。所以当你遇到同样的问题,为什么要去想着创建一个解决方案而不是用现成的并且被证明是有效的呢?
8+
9+
10+
11+
2。访问者模式解决了什么问题?
12+
1)对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
13+
2)需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。
14+
15+
16+
17+
3。访问者模式使用场景
18+
1)对象结构比较稳定,但经常需要在此对象结构上定义新的操作
19+
20+
2)需要对一个对象结构中的对象进行很多不同的且不相关的操作,而需要避免这些操作“污染”这些对象的类,也不希望在增加新操作时修改这些类。
21+
22+
比如:访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。
23+
24+
25+
26+
数据类只提供一个数据处理的接口,而数据类的处理方法我们叫它访问者
27+
28+
下面例子可以实现:安排不同年份的财务报表给不同的角色分析,这就是访问者模式的魅力;访问者模式的核心是在保持原有数据结构的基础上,实现多种数据的处理方法,该方法的角色就是访问者。
29+
30+
31+
32+
4。访问者模式优点
33+
1)使得数据结构和作用于结构上的操作解耦,使得操作集合可以独立变化。
34+
35+
2)添加新的操作或者说访问者会非常容易。
36+
37+
3)将对各个元素的一组操作集中在一个访问者类当中。
38+
39+
4)使得类层次结构不改变的情况下,可以针对各个层次做出不同的操作,而不影响类层次结构的完整性。
40+
41+
5)可以跨越类层次结构,访问不同层次的元素类,做出相应的操作。
42+
6)如果操作的逻辑改变,我们只需要改变访问者的实现就够了,而不用去修改其他所有的商品类。
43+
44+
7)添加新类别的商品到系统变得容易。只需要改变一下访问者接口以及其实现。已经存在的商品类别不会被干扰影响。
45+
46+
47+
48+
5。访问者模式缺点
49+
1)增加新的元素会非常困难。
50+
51+
2)实现起来比较复杂,会增加系统的复杂性。
52+
53+
3)破坏封装,如果将访问行为放在各个元素中,则可以不暴露元素的内部结构和状态,但使用访问者模式的时候,为了让访问者能获取到所关心的信息,元素类不得不暴露出一些内部的状态和结构,就像收入和支出类必须提供访问金额和单子的项目的方法一样。
54+
55+
4)visit()方法的返回值的类型在设计系统式就需要明确。不然,就需要修改访问者的接口以及所有接口实现。另外如果访问者接口的实现太多,系统的扩展性就会下降。
56+
57+
"""
58+
59+
60+
class Finance:
61+
def __init__(self):
62+
self.salesvolume = None # 销售额
63+
self.cost = None # 成本
64+
self.history_salesvolume = None # 历史销售额
65+
self.history_cost = None # 历史成本
66+
67+
def set_salesvolume(self, value):
68+
self.salesvolume = value
69+
70+
def set_cost(self, value):
71+
self.cost = value
72+
73+
def set_history_salesvolume(self, value):
74+
self.history_salesvolume = value
75+
76+
def set_history_cost(self, value):
77+
self.history_cost = value
78+
79+
def accept(self, visitor):
80+
pass
81+
82+
83+
# 2018年的财务情况
84+
class Finance_year(Finance):
85+
def __init__(self, year):
86+
Finance.__init__(self)
87+
self.analyst = []
88+
self.year = year
89+
90+
def add_analyst(self, worker): # 有哪些分析师来分析数据
91+
self.analyst.append(worker)
92+
93+
def accept(self): # 分析师列表里面的人去分析数据
94+
for v in self.analyst:
95+
v.visit(self)
96+
97+
98+
# 会计
99+
class Accounting:
100+
def __init__(self):
101+
self.id = '会计'
102+
self.Duty = '计算报表'
103+
104+
def visit(self, year_data):
105+
print('我现在分析的是{}年的数据'.format(year_data.year))
106+
print('我的身份是:{},职责:'.format(self.id, self.Duty))
107+
print('本年度纯利润:{}'.format(year_data.salesvolume - year_data.cost))
108+
print('---------------------------------------')
109+
110+
111+
# 财务总监
112+
class Audit:
113+
def __init__(self):
114+
self.id = '财务总监'
115+
self.Duty = '分析业绩'
116+
117+
def visit(self, year_data): # 要把具体哪一年的数据传给分析师,让分析师去分析
118+
print('我现在分析的是{}年的数据'.format(year_data.year))
119+
print('我的身份是:{},职责:'.format(self.id, self.Duty))
120+
if year_data.salesvolume - year_data.cost > year_data.history_salesvolume - year_data.history_cost:
121+
msg = '较同期上涨'
122+
else:
123+
msg = '较同期下跌'
124+
print('本年度公司业绩:{}'.format(msg))
125+
print('---------------------------------')
126+
127+
128+
# 战略顾问
129+
class Advisor:
130+
def __init__(self):
131+
self.id = '战略顾问'
132+
self.Duty = '制定明年策略'
133+
134+
def visit(self, year_data):
135+
print('我现在分析的是{}年的数据'.format(year_data.year))
136+
print('我的身份是:{},职责:'.format(self.id, self.Duty))
137+
if year_data.salesvolume > year_data.history_salesvolume:
138+
msg = '行业上涨,扩大规模'
139+
else:
140+
msg = '行业下跌,减少规模'
141+
print('本年度公司业绩:{}'.format(msg))
142+
print('------------------------------')
143+
144+
145+
# 执行分析
146+
class AnalyseData:
147+
def __init__(self):
148+
self.datalist = [] # 需要处理的数据列表,
149+
150+
def add_data(self, year_data):
151+
self.datalist.append(year_data)
152+
153+
def remove_data(self, year_data):
154+
self.datalist.remove(year_data)
155+
156+
def visit(self):
157+
for d in self.datalist:
158+
d.accept()
159+
160+
161+
if __name__ == '__main__':
162+
w = AnalyseData() # 计划安排财务,总监,顾问对2018年数据处理
163+
finance_2018 = Finance_year(2018) # 2018年的财务数据
164+
finance_2018.set_salesvolume(200)
165+
finance_2018.set_cost(90)
166+
finance_2018.set_history_salesvolume(190)
167+
finance_2018.set_history_cost(80)
168+
169+
accounting = Accounting()
170+
audit = Audit()
171+
advisor = Advisor()
172+
173+
finance_2018.add_analyst(accounting) # 会计参与2018年的数据分析,然后执行了自己的visit方法
174+
finance_2018.add_analyst(audit)
175+
finance_2018.add_analyst(advisor)
176+
177+
# finance_2018.accept() #也可以直接这样调用
178+
w.add_data(finance_2018)
179+
w.visit()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:49
4+
5+
class AccountIterator():
6+
def __init__(self, accounts):
7+
self.accounts = accounts # 账户集合
8+
self.index = 0
9+
10+
def __iter__(self):
11+
return self
12+
13+
def __next__(self):
14+
if self.index >= len(self.accounts):
15+
raise StopIteration("到头了...")
16+
else:
17+
self.index += 1
18+
return self.accounts[self.index - 1]
19+
20+
21+
if __name__ == '__main__':
22+
account_iter = AccountIterator(['a','b','c','d'])
23+
print(next(account_iter))
24+
print('----')
25+
for a in account_iter:
26+
print(a)

‎行为型模式-迭代器模式.py

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:39
4+
"""
5+
迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式。这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
6+
7+
迭代器模式属于行为型模式。
8+
9+
介绍
10+
意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。
11+
12+
主要解决:不同的方式来遍历整个整合对象。
13+
14+
何时使用:遍历一个聚合对象。
15+
16+
如何解决:把在元素之间游走的责任交给迭代器,而不是聚合对象。
17+
18+
关键代码:定义接口:hasNext, next。
19+
20+
应用实例:JAVA 中的 iterator。
21+
22+
优点: 1、它支持以不同的方式遍历一个聚合对象。 2、迭代器简化了聚合类。 3、在同一个聚合上可以有多个遍历。 4、在迭代器模式中,增加新的聚合类和迭代器类都很方便,无须修改原有代码。
23+
24+
缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性。
25+
26+
使用场景: 1、访问一个聚合对象的内容而无须暴露它的内部表示。 2、需要为聚合对象提供多种遍历方式。 3、为遍历不同的聚合结构提供一个统一的接口。
27+
28+
注意事项:迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可让外部代码透明地访问集合内部的数据。
29+
30+
python有更pythonic的方式。
31+
"""
32+
33+
from abc import ABCMeta, abstractmethod
34+
35+
class Iterator(metaclass=ABCMeta):
36+
37+
@abstractmethod
38+
def hasNext(self):
39+
pass
40+
41+
@abstractmethod
42+
def next(self):
43+
pass
44+
45+
class ConcreteIterator(Iterator):
46+
47+
def __init__(self, alist):
48+
self.alist = alist
49+
50+
def hasNext(self):
51+
'''是否还有下一个元素'''
52+
return self.alist != []
53+
54+
def next(self):
55+
'''返回下一个元素'''
56+
return self.alist.pop(0)
57+
58+
59+
class Aggregate(object):
60+
61+
def iterator(self):
62+
pass
63+
64+
class ConcreteAggregate(Aggregate):
65+
66+
def __init__(self, alist):
67+
self.alist = alist
68+
69+
def iterator(self):
70+
'''返回迭代器对象'''
71+
return ConcreteIterator(self.alist)
72+
73+
74+
if __name__ == "__main__":
75+
concreteAggregate = ConcreteAggregate([1, 2, 3])
76+
concreteIterator = concreteAggregate.iterator()
77+
while concreteIterator.hasNext():
78+
print (concreteIterator.next())

‎行为型模式-迭代器模式3.py

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -*- coding: utf-8 -*-
2+
# @Author : ydf
3+
# @Time : 2019/10/9 0009 11:56
4+
5+
from __future__ import print_function
6+
7+
8+
def count_to(count):
9+
"""Counts by word numbers, up to a maximum of five"""
10+
numbers = ["one", "two", "three", "four", "five"]
11+
for number in numbers[:count]:
12+
yield number
13+
14+
15+
# Test the generator
16+
count_to_two = lambda: count_to(2)
17+
count_to_five = lambda: count_to(5)
18+
19+
20+
if __name__ == "__main__":
21+
for number in count_to_two():
22+
print(number)
23+
24+
25+
for number in count_to_five():
26+
print(number)

0 commit comments

Comments
 (0)
Please sign in to comment.