大牧絮叨设计模式:建造者模式

2019-07-23 10:11:48 浏览数 (1)

1、 建造模式 概述

建造模式(Builder)[GOF95]是一种对象的创造模式。主要责任是在程序中创建较为复杂的对象,企业项目中在运行环境初始化时经常使用的一种创建模式。

1.1、 核心组件

建造模式和工厂模式极为相似,都是将对象的构建过程和对象的业务处理分离开来,让不同的类型分别承担对象的创建和对象的使用的责任。

建造模式在构建对象的过程中,目标对象一般都是较为复杂的多个对象或者组件内聚并添加一定业务逻辑的对象组件,并且内部对象构建过程区分前后顺序,核心组件如下:

  • 抽象建造者(Builder):规范建造者的一个抽象接口,规范产品建造过程中的步骤和规范,该接口独立于业务逻辑之外,是基于功能拓展的一个抽象依赖。
  • 具体建造者(ConcreteBuilder):该类型与具体业务逻辑紧密相关,实现了抽象建造者接口,是具体产品构建过程的执行者。
  • 零件/聚合对象(AggregationProduct):该类型的对象是最终对象中包含的具体组成部分,该组成部分可能是对象,也可能是组件或者业务逻辑。
  • 产品对象(Product):最终的产品对象,该产品对象是具体建造者最终返回的构建结果,也是我们建造者模式最终产生的和业务逻辑紧密结合的对象。

image.png

1.2、 优点缺陷

优点:

复杂对象的创建分步骤执行,开发难度降低,可读性提升

对象的创建过程和业务处理过程解耦合

缺陷:

系统复杂度提升

系统资源消耗增加

2、 Java 实现

2.1、 抽象建造者Builder

代码语言:javascript复制
package com.damu.builder;

/**
 * <p>项目文档: 产品 抽象建造者 </p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public interface Builder<T> {
    /**
     * 第一个构建步骤
     */
    void builderPart1();

    /**
     * 第二个构建步骤
     */
    void builderPart2();

    /**
     * 获取最终产品
     * @return 最终产品
     */
    T retrieveResult();
}

2.2、 内聚组件Aggregation Product

代码语言:javascript复制
package com.damu.product;

/**
 * <p>项目文档: 复杂对象-组成部分1-eg:楼房</p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public class Part1Component {

    private String information;

    public Part1Component(String information) {
        this.information = information;
    }

    public String getInformation() {
        return information;
    }

    public void setInformation(String information) {
        this.information = information;
    }
}
代码语言:javascript复制
package com.damu.product;

/**
 * <p>项目文档: 复杂对象-组成部分1-eg:物业</p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public class Part2Component {

    private String information;

    public Part2Component(String information) {
        this.information = information;
    }

    public String getInformation() {
        return information;
    }

    public void setInformation(String information) {
        this.information = information;
    }
}

2.3、 具体产品Product

代码语言:javascript复制
package com.damu.product;

/**
 * <p>项目文档: 具体产品类-eg:小区</p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public class Product {
    private String information;
    private Part1Component part1;
    private Part2Component part2;

    public String getInformation() {
        return information;
    }

    public void setInformation(String information) {
        this.information = information;
    }

    public Part1Component getPart1() {
        return part1;
    }

    public void setPart1(Part1Component part1) {
        this.part1 = part1;
    }

    public Part2Component getPart2() {
        return part2;
    }

    public void setPart2(Part2Component part2) {
        this.part2 = part2;
    }
}

2.4、 具体建造者ConcreteBuilder

代码语言:javascript复制
package com.damu.builder;

import com.damu.product.Part1Component;
import com.damu.product.Part2Component;
import com.damu.product.Product;

/**
 * <p>项目文档: 具体建造者</p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public class ConcreteBuilder implements Builder<Product> {

    private Product product;
    @Override
    public void builderPart1() {
        // builder part1
        Part1Component part1 = new Part1Component("国际工厂-盖楼");
        // other business procedure
        // aggregation
        product.setPart1(part1);
    }

    @Override
    public void builderPart2() {
        // builder part2
        Part2Component part2 = new Part2Component("华夏物理-管理");
        // other business procedure
        // aggregation
        product.setPart2(part2);
    }

    @Override
    public Product retrieveResult() {
        // builder product
        product = new Product();
        product.setInformation("清风小区");
        // step1
        this.builderPart1();
        // other business procedure
        // step2
        this.builderPart2();
        return product;
    }
}

2.5、业务消费者Consumer

代码语言:javascript复制
package com.damu.main;

import com.damu.builder.Builder;
import com.damu.builder.ConcreteBuilder;
import com.damu.product.Product;

/**
 * <p>项目文档: 消费者</p>
 *
 * @author <a href="https://github.com/laomu/laomu.github.io">大牧</a>
 * @version V1.0
 */
public class Consumer {
    public static void main(String[] args) {
        // 获取建造工厂
        Builder<Product> builder = new ConcreteBuilder();

        // 获取小区对象
        Product product = builder.retrieveResult();

        System.out.println(product);
    }
}
代码语言:javascript复制
# 执行结果
Product{information='清风小区', part1=Part1Component{information='国际工厂-盖楼'}, part2=Part2Component{information='华夏物理-管理'}}

3、 Python 实现

3.1、 抽象建造者Builder

代码语言:javascript复制
import abc


class Builder(metaclass=abc.ABCMeta):
    """抽象建造者"""
    def retrieve_result(self):
        """获取产品对象的方法"""
        raise NotImplemented("该方法必须在子类中实现")

3.2、 内聚组件Aggregation Product

代码语言:javascript复制
class Part1Component:
    """产品部件1"""
    pass


class Part2Component:
    """产品部件2"""
    pass

3.3、 具体产品Product

代码语言:javascript复制
import abc

class Product(metaclass=abc.ABCMeta):
    """建造者产品接口"""

    @abc.abstractmethod
    def information(self):
        raise NotImplemented("该方法必须实现.")
        
class ConcreteProduct(Product):
    """具体产品对象"""

    def __init__(self):
        self.part1 = None
        self.part2 = None

    def information(self):
        print("目标对象")

3.4、 具体建造者ConcreteBuilder

代码语言:javascript复制
class ConcreteBuilder(Builder):
    """具体建造类"""

    def __init__(self):
        """初始化"""
        self.product = ConcreteProduct()

    def __build_part1(self):
        # 构建零件对象
        part1_component = Part1Component()
        # 业务受理
        # 聚合
        self.product.part1 = part1_component

    def __build_part2(self):
        # 构建零件对象
        part2_component = Part2Component()
        # 业务受理
        # 聚合
        self.product.part2 = part2_component

    def retrieve_result(self):
        return self.product

3.5、业务消费者Consumer

代码语言:javascript复制
if __name__ == "__main__":
    """测试代码"""
    # 创建建造者对象
    builder = ConcreteBuilder()
    # 建造目标对象
    product = builder.retrieve_result()
    print(product)

4、 Go 实现

4.1、 抽象建造者Builder

代码语言:javascript复制
type Builder interface {
  SetName(name string) Builder
  SetArms(arms string) Builder
  Build() *Character
}

4.2、 具体产品Product

代码语言:javascript复制
type Character struct {
  Name string
  Arms string
}

func (p *Character) SetName(name string) {
  p.Name = name
}

func (p *Character) SetArms(arms string) {
  p.Arms = arms
}

func (p Character) GetName() string {
  return p.Name
}

func (p Character) GetArms() string {
  return p.Arms
}

4.3、 具体建造者ConcreteBuilder

代码语言:javascript复制
type CharacterBuilder struct {
  character *Character
}

func (p *CharacterBuilder) SetName(name string) Builder {
  if p.character == nil {
    p.character = &Character{}
  }
  p.character.SetName(name)
  return p
}

func (p *CharacterBuilder) SetArms(arms string) Builder {
  if p.character == nil {
    p.character = &Character{}
  }
  p.character.SetArms(arms)
  return p
}

func (p *CharacterBuilder) Build() *Character {
  return p.character
}

4.4、业务消费者Consumer

代码语言:javascript复制
type Consumer struct {
  builder Builder
}

func (p Director) Create(name string, arms string) *Character {
  return p.builder.SetName(name).SetArms(arms).Build()
}

func main() {
  var builder Builder = &CharacterBuilder {}
  var consumer *Consumer = &Consumer {builder: builder}
  var character *Character = director.Create("loader", "AK47")
  fmt.Println(character.GetName()   ","   character.GetArms())
}

0 人点赞