创建型模式:建造者模式(Builder)

来源:互联网 发布:足球大师卡卡捏脸数据 编辑:程序博客网 时间:2024/06/07 01:35

意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

结构:
builder

示例:
builder_example

Builder(TextConverter):为创建产品对象的各个部件提供抽象接口。

class TextConverter(ABC):    @abstractmethod    def convert_character(self, char):        """转换普通文本"""    @abstractmethod    def convert_font_change(self, font):        """转换RTF控制字"""    @abstractmethod    def convert_paragraph(self):        """转换RTF标记"""

ConcreteBuilder(ASCIIConverter、TeXConverter、TextWidgetConverter):实现Builder接口来构造或装配产品的各个部件,提供一个检索产品的接口(返回产品对象)。

class ASCIIConverter(TextConverter):    def __init__(self):        self.__ascii_text = ASCIIText()    def convert_character(self, char):        converted_char = ascii(char)        print('convert character(%s) with ascii' % converted_char)        self.__ascii_text.char.append(converted_char)    def convert_font_change(self, font):        raise AttributeError('ascii converter cant convert font change')    def convert_paragraph(self):        raise AttributeError('ascii converter cant convert paragraph')    def get_ascii_text(self):        """返回ascii编码文本"""        return self.__ascii_textclass TeXConverter(TextConverter):    def __init__(self):        self.__tex_text = TeXText()    def convert_character(self, char):        converted_char = char.upper()        print('convert character(%s) with TeX' % converted_char)        self.__tex_text.char.append(converted_char)    def convert_font_change(self, font):        converted_font = font.upper()        print('convert font_change(%s) with TeX' % converted_font)        self.__tex_text.font.append(converted_font)    def convert_paragraph(self):        print('convert paragraph with TeX')        self.__tex_text.para.append('para')    def get_tex_text(self):        """返回tex风格文本"""        return self.__tex_textclass TextWidgetConverter(TextConverter):    def __init__(self):        self.__text_widget = TextWidget()    def convert_character(self, char):        print('convert character(%s) with TextWidget' % char)        self.__text_widget.char.append(char)    def convert_font_change(self, font):        print('convert font_change(%s) with TextWidget' % font)        self.__text_widget.font.append(font)    def convert_paragraph(self):        print('convert paragraph with TextWidget')        self.__text_widget.para.append('para')    def get_text_widget(self):        """返回文本组件"""        return self.__text_widget

Director(RTFReader):构造一个使用Builder接口的对象,提供了construct建造方法,该方法中应该调用Builder中的创建各部件的接口(此时实际装配了一个完整的产品)。

class RTFReader:    def __init__(self, builder: TextConverter):        self.builder = builder    def parse_RTF(self, rtf_list):        """construct()建造方法"""        for rtf in rtf_list:            if rtf.sign == 'CHAR':                self.builder.convert_character(rtf.char)            elif rtf.sign == 'FONT':                self.builder.convert_font_change(rtf.font)            elif rtf.sign == 'PARA':                self.builder.convert_paragraph()

Product(ASCIIText、TeXText、TextWidget):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。

class ASCIIText:    def __init__(self):        self.char = []    def show(self):        print('ascii text: %s' % ''.join(self.char))class TeXText:    def __init__(self):        self.char = []        self.font = []        self.para = []    def show(self):        print('TeX char: %s' % ''.join(self.char))        print('TeX font: %s' % ''.join(self.font))        print('TeX para: %s' % ''.join(self.para))class TextWidget:    def __init__(self, window='PC_WINDOW'):        self.window = window        self.char = []        self.font = []        self.para = []    def show(self):        print('show text: %s in %s' % (''.join(self.char), self.window))        print('show text: %s in %s' % (''.join(self.font), self.window))        print('show text: %s in %s' % (''.join(self.para), self.window))

Client:利用所需的Builder创建Director对象,利用建造方法construct(),构建产品的各个部件,最后从Builder中获取完整的产品。

交互图:
builder_example2

分析:

  1. Builder提供给Directror构造产品的抽象接口,该接口隐藏了产品的表示和内部结构,以及产品是如何装配的。当改变产品的内部结构时,只需要重新定义一个ConcreteBuilder,并改变其内部的部件装备的结构(如将TeX风格的普通文本改为str.lower()时,只要重新定义ConcreteBuilder,并修改部件的装配方法)。
  2. 对产品的构造过程进行更精细的控制。产品是在导向者Director的控制下,一步一步的构造完成的,且仅当各个部件构造结束成为完整的产品时才从Builder中取回该产品。
  3. Builder着重于一步一步构造一个复杂对象,且在最后一步构造完成时返回。而Abstract Factory着重于多个系列同个产品族的产品对象,且该对象是立刻返回的。
原创粉丝点击