策略模式:
要完成一个任务,但完成任务有多种方式A、B、C,那么可以定义一组算法,将每个算法都封装起来,分别对应每个方式A、B、C,并使他们之间可互换。
在策略模式中,客户端定义一个上下文(Context)对象,该对象包含一个抽象策略类的引用,策略类定义了一个算法族,可以通过继承或实现接口的方式来扩展新的算法。客户端在运行时可以根据需要将不同的策略类传递给上下文对象,上下文对象在运行时调用策略类的算法。
实例:
如现在超市前台付款方式,会常遇到刷卡、某宝支付、某信支付等方式。
公司有新产品上线,需要通知客户,通知方式有:短信通知、邮件通知。
代码1:
使用策略模式实现一个简单的排序算法,可以通过选择不同的算法来实现不同的排序方式。
# 抽象策略类
class SortStrategy:
def sort(self, data):
pass
# 具体策略类1:冒泡排序
class BubbleSortStrategy(SortStrategy):
def sort(self, data):
for i in range(len(data)):
for j in range(len(data) - i - 1):
if data[j] > data[j + 1]:
data[j], data[j + 1] = data[j + 1], data[j]
# 具体策略类2:快速排序
class QuickSortStrategy(SortStrategy):
def sort(self, data):
if len(data) <= 1:
return data
pivot = data[0]
left, right = [], []
for i in range(1, len(data)):
if data[i] < pivot:
left.append(data[i])
else:
right.append(data[i])
return self.sort(left) + [pivot] + self.sort(right)
# 上下文类
class SortContext:
def __init__(self, strategy):
self.strategy = strategy
def set_strategy(self, strategy):
self.strategy = strategy
def sort(self, data):
return self.strategy.sort(data)
# 客户端
data = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
context = SortContext(BubbleSortStrategy())
print(context.sort(data))
context.set_strategy(QuickSortStrategy())
print(context.sort(data))
代码2:
假设某司维护着一些客户资料,需要在该司有新产品上市或者举行新活动时通知客户。现通知客户的方式有两种:短信通知、邮件通知。应如何设计该系统的客户通知部分?为解决该问题,我们先构造客户类,包括客户常用的联系方式和基本信息,同时也包括要发送的内容。
class Customer(object):
customer_name=""
snd_way=""
info=""
phone=""
email=""
def set_phone(self,phone):
self.phone=phone
def set_email(self,mail):
self.email=mail
def get_phone(self):
return self.phone
def get_email(self):
return self.email
def set_message(self,message):
self.message=message
def set_sendWay(self,send_way):
self.send_way=send_way
def sendmsg(self):
self.send_way.send(self.message)
class Sender(object):
dst_code=""
def setCode(self,code):
self.dst_code=code
def send(self,message):
pass
class EmailSender(Sender):
def send(self,message):
print "EMAIL_ADDRESS:%s EMAIL:%s"%(self.dst_code,message)
class PhoneSender(Sender)
def send(self,message)
print "PHONE_ADDRESS:%s PHONE:%s"%(self.dst_code,message)
if __name__=="__main__":
customer=Customer()
customer.set_phone("10023456789")
customer.set_email("customer_x@xmail.com")
customer.set_message("Welcome to our new party!")
mail_sender=EmailSender()
mail_sender.setCode(customer.get_email())
customer.set_sendWay(mail_sender)
customer.sendmsg()
仔细比较一下桥接模式和策略模式,桥接模式比策略模式多了对一种角色(抽象角色)的抽象。二者结构的高度同构,也只能让我们从使用意图上去区分两种模式:桥接模式解决抽象角色和实现角色都可以扩展的问题;而策略模式解决算法切换和扩展的问题。