您的位置:首页 > 编程语言 > Python开发

Python实现设计模式--05.建造者模式(Builder Pattern)

2017-08-03 23:14 726 查看
建造者模式是一种创建类的模式,它尽可能的保证代码的复用性,而且可读性也非常好(最终产生对象的过程对调用方是透明的)。

很多朋友应该都做过微信公众号或者支付宝服务窗的消息推送,下面是微信公众平台给的消息示例:

{
"touser":"OPENID",
"template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
"url":"http://weixin.qq.com/download",
"miniprogram":{
"appid":"xiaochengxuappid12345",
"pagepath":"index?foo=bar"
},
"data":{
"first":{
"value":"恭喜你购买成功!",
"color":"#173177"
},
"keynote1":{
"value":"巧克力",
"color":"#173177"
},
"keynote2":{
"value":"39.8元",
"color":"#173177"
},
"keynote3":{
"value":"2014年9月22日",
"color":"#173177"
},
"remark":{
"value":"欢迎再次购买!",
"color":"#173177"
}
}
}

具体参数可在公众平台开发者文档查看。现在的问题是如何设计消息模版呢?我身边有的同事是用字符串替换,有的对各个模版建立一个类,这里我不往深里讨论方案对优劣,本节结束后读者们可以尝试做下对比。下面我给出一种建造者模式对做法,创建builder类如下(简便起见,去掉了miniprogram参数):

# -*- coding: utf-8 -*-

from collections import OrderedDict
import json

# 模版中“data”节点的各个元素的数据结构
class Metadata:
def __init__(self, value, color):
self.value = value
self.color = color

# 微信消息的建造器
class MessageBuilder:
__contentDict = OrderedDict()  # 定义整个模版的数据结构,保持添加的顺序
__dataDict = OrderedDict()  # 定义data节点的数据结构,保持添加的顺序
__dataNoteNext = 1  # data节点要添加的下一个元素的序号

def __init__(self, touser, template_id, url):
self.__contentDict['touser'] = touser
self.__contentDict['template_id'] = template_id
self.__contentDict['url'] = url
self.__contentDict['data'] = self.__dataDict

def add_first_data(self, value, color):
data = Metadata(value, color)
self.__dataDict['first'] = data
return self

def add_remark_data(self, value, color):
data = Metadata(value, color)
self.__dataDict['remark'] = data
return self

def add_note_data(self, value, color):
data = Metadata(value, color)
self.__dataDict['keynote' + str(self.__dataNoteNext)] = data
self.__dataNoteNext += 1
return self

def build(self):
# 为打印出来看的方便,这里将json序列化后的结果缩进2个空格,并且不把中文转为unicode
return json.dumps(self.__contentDict, default=lambda o: o.__dict__, indent=2, ensure_ascii=False)
有两点要说明下:

建造者内部的字典采用OrderedDict,是为了保持顺序与微信示例一致
建造者每个方法都返回了本对象的引用,这是一个很常用的技巧
建造者有了,下面我们来生成两条消息。前几天我在丰巢快递柜寄了票件,下图是我收到的其中两个微信通知:


  


我们模拟作如上两条微信消息:

if __name__ == '__main__':
    order_builder = MessageBuilder('user111111', 'template_id_order', '') \
        .add_first_data('您的寄件订单已经生成啦!请打包好您的包裹前往柜机投递。', '#173177') \
        .add_note_data('03226580', '#173177') \
        .add_note_data('10(小格);14(中格);18(大格);', '#173177') \
        .add_note_data('顺丰速运', '#173177') \
        .add_remark_data('“一分钱寄全国”优惠券以放入到你的账户,在柜机支付时记得使用哦。', '#173177')
    print('生成下单通知微信消息')
    print(order_builder.build())

    print()

    send_builder = MessageBuilder('user222222', 'template_id_send', 'http://balabala') \
        .add_first_data('丰巢已收到您的包裹,并已通知快递员来收取啦!', '#173177') \
        .add_note_data('顺丰速运', '#173177') \
        .add_note_data('422154541545', '#173177') \
        .add_note_data('某地址某地址某地址某地址', '#173177') \
        .add_note_data('2017-07-31 11:20', '#173177') \
        .add_remark_data('点击详情查看物流进度', '#173177')
    print('生成投递微信消息')
    print(send_builder.build())
运行结果:
生成下单通知微信消息
{
  "touser": "user111111",
  "template_id": "template_id_order",
  "url": "",
  "data": {
    "first": {
      "color": "#173177",
      "value": "您的寄件订单已经生成啦!请打包好您的包裹前往柜机投递。"
    },
    "keynote1": {
      "color": "#173177",
      "value": "03226580"
    },
    "keynote2": {
      "color": "#173177",
      "value": "10(小格);14(中格);18(大格);"
    },
    "keynote3": {
      "color": "#173177",
      "value": "顺丰速运"
    },
    "remark": {
      "color": "#173177",
      "value": "“一分钱寄全国”优惠券以放入到你的账户,在柜机支付时记得使用哦。"
    }
  }
}

生成投递微信消息
{
  "touser": "user222222",
  "template_id": "template_id_send",
  "url": "http://balabala",
  "data": {
    "first": {
      "color": "#173177",
      "value": "丰巢已收到您的包裹,并已通知快递员来收取啦!"
    },
    "keynote1": {
      "color": "#173177",
      "value": "顺丰速运"
    },
    "keynote2": {
      "color": "#173177",
      "value": "422154541545"
    },
    "keynote3": {
      "color": "#173177",
      "value": "某地址某地址某地址某地址"
    },
    "remark": {
      "color": "#173177",
      "value": "点击详情查看物流进度"
    },
    "keynote4": {
      "color": "#173177",
      "value": "2017-07-31 11:20"
    }
  }
}

本人经验,这类情形下,建造者模式使得代码更加清晰易懂,读者有没有一点点启发呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 设计模式