【每日一记】设计模式——建造者模式

23 篇文章 0 订阅
23 篇文章 0 订阅

概述

  • 定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
  • 适用场景
    1. 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时
    2. 当构造过程必须允许被构造的对象有不同表示时
  • 通俗理解:一个对象包含多个部分,每个部分可能有多种不同的形式或相互依赖,但是对象总体结构不变,那么这时就可以使用建造者模式
  • 优点:通过建造者模式,使客户端不必知晓复杂对象的构建过程,将产品的结构和产品的零件的建造过程对客户端隐藏起来,把对建造过程进行指挥的责任和具体建造者零件的责任分割开来,达到责任划分和封装的目的

实现

以创建不同角色为例展示具体实现过程

// 角色基类,由头和身体两部分组成
public class Role {
    private String head;
    private String body;

    public String getHead() {
        return head;
    }

    public void setHead(String head) {
        this.head = head;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }
}
// 角色A
class RoleA extends Role {
    public RoleA() {
        System.out.println("create RoleA");
    }
}
// 角色B
class RoleB extends Role {
    public RoleB() {
        System.out.println("create RoleB");
    }
}
// 建造者接口
// 当需要增加待建造的类时只需添加对应的建造者即可
public interface IBuilder {
    void buildHead();

    void buildBody();

    Role getRole();
}
// 角色A的建造者,负责建造角色A的各个部分
class RoleABuilder implements IBuilder {
    private Role role = new RoleA();

    @Override
    public void buildHead() {
        role.setHead("RoleA's head");
    }

    @Override
    public void buildBody() {
        role.setBody("RoleA's body");
    }

    @Override
    public Role getRole() {
        return role;
    }

}
// 角色B的建造者,负责建造角色B的各个部分
class RoleBBuilder implements IBuilder {
    private Role role = new RoleB();

    @Override
    public void buildHead() {
        role.setHead("RoleB's head");
    }

    @Override
    public void buildBody() {
        role.setBody("RoleB's body");
    }

    @Override
    public Role getRole() {
        return role;
    }

}
// 导演者,负责整个建造流程
// 当要建造的类只有一个时,可以将Director的代码合入到Builder中
public class Director {
    public Role constructRole(IBuilder builder) {
        builder.buildHead();
        builder.buildBody();
        return builder.getRole();
    }
}
// 客户端
public class Client {
    public static void main(String[] args) {
        IBuilder builderA = new RoleABuilder();
        IBuilder builderB = new RoleBBuilder();
        Director director = new Director();
        Role roleA = director.constructRole(builderA);
        System.out.println(roleA.getHead() + ", " + roleA.getBody());
        Role roleB = director.constructRole(builderB);
        System.out.println(roleB.getHead() + ", " + roleB.getBody());
    }
}

建造者模式中两个重要角色:

  • builder:这里是定义了如何构建各个部件,负责各个部分的建造过程
  • director:这里定义如何组合来构建产品,负责整体建造过程,一般分步骤的来执行

实际应用

java.util.Calendar.Builder

// 负责构建对象整体的方法,相当于Director
public Calendar build() {
    // 根据设置建造各个部分
    if (locale == null) {
        locale = Locale.getDefault();
    }
    if (zone == null) {
        zone = TimeZone.getDefault();
    }
    Calendar cal;
    if (type == null) {
        type = locale.getUnicodeLocaleType("ca");
    }
    if (type == null) {
        if (locale.getCountry() == "TH"
            && locale.getLanguage() == "th") {
            type = "buddhist";
        } else {
            type = "gregory";
        }
    }
    switch (type) {
    case "gregory":
        cal = new GregorianCalendar(zone, locale, true);
        break;
    case "iso8601":
        GregorianCalendar gcal = new GregorianCalendar(zone, locale, true);
        // make gcal a proleptic Gregorian
        gcal.setGregorianChange(new Date(Long.MIN_VALUE));
        // and week definition to be compatible with ISO 8601
        setWeekDefinition(MONDAY, 4);
        cal = gcal;
        break;
    case "buddhist":
        cal = new BuddhistCalendar(zone, locale);
        cal.clear();
        break;
    case "japanese":
        cal = new JapaneseImperialCalendar(zone, locale, true);
        break;
    default:
        throw new IllegalArgumentException("unknown calendar type: " + type);
    }
    cal.setLenient(lenient);
    if (firstDayOfWeek != 0) {
        cal.setFirstDayOfWeek(firstDayOfWeek);
        cal.setMinimalDaysInFirstWeek(minimalDaysInFirstWeek);
    }
    if (isInstantSet()) {
        cal.setTimeInMillis(instant);
        cal.complete();
        return cal;
    }

    ...

    // 返回建造好的对象
    return cal;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值