python创建型设计模式——建造者模式
2017-01-02 20:27
435 查看
建造者模式
与工厂模式相似,用于创建需要由多个对象组成的复杂对象。区别在于他不仅提供了创建复杂对象所需要的方法,而且保存了复杂对象里的各个部分的细节。适用于需要把复杂对象各个部分的细节与其创建流程相分离的场合。表单生成程序的例子,分别生成HTML和ThinkerGUI表单
最顶层调用
创建两个表单,并分别写入对应文件中,都会调用create_login_form()并传入建造者对象def main(): if len(sys.argv) > 1 and sys.argv[1] == "-P": # For regression testing print(create_login_form(HtmlFormBuilder())) print(create_login_form(TkFormBuilder())) return htmlFilename = os.path.join(tempfile.gettempdir(), "login.html") htmlForm = create_login_form(HtmlFormBuilder()) with open(htmlFilename, "w", encoding="utf-8") as file: file.write(htmlForm) print("wrote", htmlFilename) tkFilename = os.path.join(tempfile.gettempdir(), "login.py") tkForm = create_login_form(TkFormBuilder()) with open(tkFilename, "w", encoding="utf-8") as file: file.write(tkForm) print("wrote", tkFilename)
create_login_form()函数
调用builder的设置方法,然后由builder拼接对象,返回复杂的对象。与工厂模式的却别在于,工厂模式这里是直接由工厂创建相关简单对象以及复杂对象,复杂对象调用自己的方法进行拼接,然后返回自己def create_login_form(builder): builder.add_title("Login") builder.add_label("Username", 0, 0, target="username") builder.add_entry("username", 0, 1) builder.add_label("Password", 1, 0, target="password") builder.add_entry("password", 1, 1, kind="password") builder.add_button("Login", 2, 0) builder.add_button("Cancel", 2, 1) return builder.form()
建造者类
HtmlFormBuilder类表单中的控件保存在items字典中,字典的键是row与column构成的二元组,值为控件html代码
class HtmlFormBuilder(AbstractFormBuilder): def __init__(self): self.title = "HtmlFormBuilder" self.items = {} def add_title(self, title): super().add_title(escape(title)) def add_label(self, text, row, column, **kwargs): self.items[(row, column)] = ('<td><label for="{}">{}:</label></td>' .format(kwargs["target"], escape(text))) def add_entry(self, variable, row, column, **kwargs): html = """<td><input name="{}" type="{}" /></td>""".format( variable, kwargs.get("kind", "text")) self.items[(row, column)] = html def add_button(self, text, row, column, **kwargs): html = """<td><input type="submit" value="{}" /></td>""".format( escape(text)) self.items[(row, column)] = html def form(self): html = ["<!doctype html>\n<html><head><title>{}</title></head>" "<body>".format(self.title), '<form><table border="0">'] thisRow = None for key, value in sorted(self.items.items()): row, column = key if thisRow is None: html.append(" <tr>") elif thisRow != row: html.append(" </tr>\n <tr>") thisRow = row html.append(" " + value) html.append(" </tr>\n</table></form></body></html>") return "\n".join(html)
TkFormBuilder类
由statement字典来存放组件创建和设置的语句,有extends()函数来扩充该字典。_canonicalize()用于格式化处理字符串,设置在数字开头的字符串前增加 “_”,并且可以根据需要,设置首字母大小写
class TkFormBuilder(AbstractFormBuilder): TEMPLATE = """#!/usr/bin/env python3 import tkinter as tk import tkinter.ttk as ttk class {name}Form(tk.Toplevel): def __init__(self, master): super().__init__(master) self.withdraw() # hide until ready to show self.title("{title}") {statements} self.bind("<Escape>", lambda *args: self.destroy()) self.deiconify() # show when widgets are created and laid out if self.winfo_viewable(): self.transient(master) self.wait_visibility() self.grab_set() self.wait_window(self) if __name__ == "__main__": application = tk.Tk() window = {name}Form(application) application.protocol("WM_DELETE_WINDOW", application.quit) application.mainloop() """ def __init__(self): self.title = "TkFormBuilder" self.statements = [] def add_title(self, title): super().add_title(title) def add_label(self, text, row, column, **kwargs): name = self._canonicalize(text) create = """self.{}Label = ttk.Label(self, text="{}:")""".format( name, text) layout = """self.{}Label.grid(row={}, column={}, sticky=tk.W, \ padx="0.75m", pady="0.75m")""".format(name, row, column) self.statements.extend((create, layout)) def add_entry(self, variable, row, column, **kwargs): name = self._canonicalize(variable) extra = "" if kwargs.get("kind") != "password" else ', show="*"' create = "self.{}Entry = ttk.Entry(self{})".format(name, extra) layout = """self.{}Entry.grid(row={}, column={}, sticky=(\ tk.W, tk.E), padx="0.75m", pady="0.75m")""".format(name, row, column) self.statements.extend((create, layout)) def add_button(self, text, row, column, **kwargs): name = self._canonicalize(text) create = ("""self.{}Button = ttk.Button(self, text="{}")""" .format(name, text)) layout = """self.{}Button.grid(row={}, column={}, padx="0.75m", \ pady="0.75m")""".format(name, row, column) self.statements.extend((create, layout)) def form(self): return TkFormBuilder.TEMPLATE.format(title=self.title, name=self._canonicalize(self.title, False), statements="\n ".join(self.statements)) def _canonicalize(self, text, startLower=True): text = re.sub(r"\W+", "", text) if text[0].isdigit(): return "_" + text return text if not startLower else text[0].lower() + text[1:]
补充知识点
python tempfile 模块http://blog.csdn.net/liangzhao_jay/article/details/17719953
python继承的实现:
基类设置mateclass参数为abc模块中的ABCMeta,并用 @abc.abstractmethod装饰器装饰抽象方法。如果这么设置,则该类将无法初始化,但是会增加运行期开销,一般采用更为宽松的做法,不用mateclass,而是直接在文档中说明,该类是抽象基类。
class AbstractFormBuilder(metaclass=abc.ABCMeta): @abc.abstractmethod def add_title(self, title): self.title = title @abc.abstractmethod def form(self): pass @abc.abstractmethod def add_label(self, text, row, column, **kwargs): pass @abc.abstractmethod def add_entry(self, variable, row, column, **kwargs): pass @abc.abstractmethod def add_button(self, text, row, column, **kwargs): pass
序列与映射的解包操作:
相关文章推荐
- 设计模式(三)建造者模式Builder(创建型)
- 设计模式笔记 3.Builder 建造者模式(创建型模式)
- 设计模式之创建型模式―― 1.6 建造者模式
- 【创建型模式】建造者模式(Builder)之23种java设计模式
- 设计模式之------创建型模式(四)-----建造者模式(Builder)
- 设计模式(三)建造者模式Builder(创建型)
- Python 设计模式系列之二: 创建型 Simple Factory 模式
- Python设计模式系列之四: 创建型Abstract Factory模式
- 设计模式(三)建造者模式Builder(创建型)
- 六.创建型设计模式——Builder Pattern(建造者模式)
- Python 设计模式系列之二: 创建型 Simple Factory 模式
- Python设计模式系列之三: 创建型Factory Method模式
- 设计模式(三)建造者模式Builder(创建型)
- python设计模式1:创建型模式
- 设计模式(七)—建造者模式(创建型)
- 设计模式---建造者模式Builder(创建型)
- Python 设计模式系列之二: 创建型 Simple Factory 模式
- PYTHON设计模式,创建型之工厂方法模式
- PYTHON设计模式,创建型之简单工厂模式
- 设计模式(三)建造者模式Builder(创建型)