【设计模式-2.5】创建型——建造者模式
  TEZNKK3IfmPf 24天前 20 0

说明:本文介绍设计模式中,创建型设计模式中的最后一个,建造者模式;

入学报道

创建型模式,关注于对象的创建,建造者模式也不例外。假设现在有一个场景,高校开学,学生、教师、职工都要办理相关的报道手续,如签到、个人信息录入、分配身份证明(学生证、教师证、职工证)等等;

首先,创建一个抽象类,如下:

(Person,人员类,有签到、个人信息、身份证明属性)

/** * 人员 */
public class Person {
     
       

    /** * 签到 */
    private String signIn;

    /** * 个人信息 */
    private String profile;

    /** * 身份证明 */
    private String idCard;

    public String getSignIn() {
     
       
        return signIn;
    }

    public void setSignIn(String signIn) {
     
       
        this.signIn = signIn;
    }

    public String getProfile() {
     
       
        return profile;
    }

    public void setProfile(String profile) {
     
       
        this.profile = profile;
    }

    public String getIdCard() {
     
       
        return idCard;
    }

    public void setIdCard(String idCard) {
     
       
        this.idCard = idCard;
    }
}

在创建具体对象之前,先创建一个抽象的建造者类,用于统一方法,定义人员对象;

(PersonBuilder,人员建造者)

/** * 抽象建造者 */
public abstract class PersonBuilder {
     
       

    Person person = new Person();

    /** * 签到行为 */
    public abstract void buildSignIn();

    /** * 录入个人信息 */
    public abstract void buildProfile();

    /** * 办理身份证明 */
    public abstract void buildIdCard();

    /** * 建造完成 * @return */
    public Person build() {
     
       
        return person;
    }
}

(Student,学生类,继承人员建造者,重写学生入学相关方法)

/** * 学生入学 */
public class Student extends PersonBuilder {
     
       
    @Override
    public void buildSignIn() {
     
       
        person.setSignIn("学生已签到");
    }

    @Override
    public void buildProfile() {
     
       
        person.setProfile("学生信息已录入");
    }

    @Override
    public void buildIdCard() {
     
       
        person.setIdCard("学生证已办理");
    }
}

(Teacher,教师类,继承人员建造者,重写教师入学相关方法)

/** * 教师入学 */
public class Teacher extends PersonBuilder {
     
       
    @Override
    public void buildSignIn() {
     
       
        person.setSignIn("老师已签到");
    }

    @Override
    public void buildProfile() {
     
       
        person.setProfile("老师个人信息已录入");
    }

    @Override
    public void buildIdCard() {
     
       
        person.setIdCard("老师身份证已办理");
    }
}

(Employee,职工类,继承人员建造者,重写职工入学相关方法)

/** * 职工入学 */
public class Employee extends PersonBuilder {
     
       
    @Override
    public void buildSignIn() {
     
       
        person.setSignIn("员工已签到");
    }

    @Override
    public void buildProfile() {
     
       
        person.setProfile("员工个人信息已录入");
    }

    @Override
    public void buildIdCard() {
     
       
        person.setIdCard("员工身份证已办理");
    }
}

再创建一个建造者控制类,协调入学后的具体事宜,如先签到、后录入个人信息,最后才发身份证明,返回建造完成的人员对象;

(PersonController,人员入学控制器)

/** * 人员入学控制器 */
public class PersonController {
     
       

    /** * 人员入学 * @return */
        public Person construct(PersonBuilder personBuilder) {
     
       
            personBuilder.buildSignIn();
            personBuilder.buildProfile();
            personBuilder.buildIdCard();
            return personBuilder.build();
        }
}

(Client,客户端,演示人员入学过程)

/** * 客户端 */
public class Client {
     
       
    public static void main(String[] args) {
     
       
        // 一个学生入学
        Person student = new PersonController().construct(new Student());
        System.out.println(student.getSignIn());
        System.out.println(student.getProfile());
        System.out.println(student.getIdCard());

        System.out.println("=====================================");

        // 一个老师入学
        Person teacher = new PersonController().construct(new Teacher());
        System.out.println(teacher.getSignIn());
        System.out.println(teacher.getProfile());
        System.out.println(teacher.getIdCard());
    }
}

(执行结果,可见对象已创建完成)

【设计模式-2.5】创建型——建造者模式

改进与优化

在《设计模式的艺术》(第一版,刘伟著)中,作者关于PersonController(人员控制器)类的作用,有两点改进与优化的地方,如下:

改进:可省略PersonController

可在抽象建造者类PersonBuilder(人员建造者)中定义一个静态的Person变量,这样就不需要额外设立一个PersonController类了,如下:

(PersonBuilder,抽象人员建造者,既统一了方法,也完成了建造的流程)

/** * 抽象建造者 */
public abstract class PersonBuilder {
     
       

    /** * 定义一个抽象的Person */
    protected static Person person = new Person();

    /** * 签到行为 */
    public abstract void buildSignIn();

    /** * 录入个人信息 */
    public abstract void buildProfile();

    /** * 办理身份证明 */
    public abstract void buildIdCard();

    /** * 建造Person * @return */
    public static Person build(PersonBuilder personBuilder) {
     
       
        personBuilder.buildSignIn();
        personBuilder.buildProfile();
        personBuilder.buildIdCard();
        return person;
    }
}

(Client,客户端,使用人员建造者的build()方法建造对象)

/** * 客户端 */
public class Client {
     
       
    public static void main(String[] args) {
     
       
        // 一个学生入学
        Person student = PersonBuilder.build(new Student());
        System.out.println(student.getSignIn());
        System.out.println(student.getProfile());
        System.out.println(student.getIdCard());

        System.out.println("=====================================");

        // 一个老师入学
        Person teacher = PersonBuilder.build(new Teacher());
        System.out.println(teacher.getSignIn());
        System.out.println(teacher.getProfile());
        System.out.println(teacher.getIdCard());
    }
}

(执行效果相同)

【设计模式-2.5】创建型——建造者模式

优化:细化建造过程

可以定义一个“钩子”方法,“钩子”方法一般是“isXXX”命名的,返回值为boolean类型。利用“钩子”方法,规定某些人员可以跳过或者必须执行某方法,来细化对象建造的流程。如规定教师人员的建造,因为教师流动不大,可以跳过录入信息流程。

就可以在PersonBuilder类中定义一个“钩子”方法,默认返回true,即默认所有人员都需要录入个人信息。如下:

/** * 抽象建造者 */
public abstract class PersonBuilder {
     
       

    /** * 定义一个抽象的Person */
    protected static Person person = new Person();

    /** * 签到行为 */
    public abstract void buildSignIn();

    /** * 录入个人信息 */
    public abstract void buildProfile();

    /** * 办理身份证明 */
    public abstract void buildIdCard();

    /** * 钩子方法:表示默认所有人都需要经过buildProfile()方法,具体由子类实现 */
    public boolean isBuildProfile() {
     
       
        return true;
    }

    /** * 建造Person * @return */
    public static Person build(PersonBuilder personBuilder) {
     
       
        personBuilder.buildSignIn();
        // 根据钩子方法判断是否需要buildProfile()
        if (personBuilder.isBuildProfile()) {
     
       
            personBuilder.buildProfile();
        }
        personBuilder.buildIdCard();
        return person;
    }
}

教师类中,可以重写这个“钩子”方法,表示不需要执行录入个人信息这个流程了。

/** * 教师入学 */
public class Teacher extends PersonBuilder {
     
       
    @Override
    public void buildSignIn() {
     
       
        person.setSignIn("老师已签到");
    }

    @Override
    public void buildProfile() {
     
       
        person.setProfile("老师个人信息已录入");
    }

    @Override
    public void buildIdCard() {
     
       
        person.setIdCard("老师身份证已办理");
    }

    @Override
    public boolean isBuildProfile() {
     
       
        return false;
    }
}

客户端代码不变,执行

/** * 客户端 */
public class Client {
     
       
    public static void main(String[] args) {
     
       
        // 一个学生入学
        Person student = PersonBuilder.build(new Student());
        System.out.println(student.getSignIn());
        System.out.println(student.getProfile());
        System.out.println(student.getIdCard());

        System.out.println("=====================================");

        // 一个老师入学
        Person teacher = PersonBuilder.build(new Teacher());
        System.out.println(teacher.getSignIn());
        System.out.println(teacher.getProfile());
        System.out.println(teacher.getIdCard());
    }
}

执行结果可以看到教师确实是没有执行录入个人信息的方法,但是因为Person是static修饰的属性,打印的是上面学生的值。

【设计模式-2.5】创建型——建造者模式

那么,如果避免这个问题值得思考,或者就不省略PersonController类。

小结

建造者模式,通过定义一个抽象建造者类,封装了对象创建的细节,另外通过“钩子”方法,可细化对象创建过程,降低了系统复杂度,维护了系统的灵活性和扩展性。

总结

本文参考《设计模式的艺术》、《秒懂设计模式》两书

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 24天前 0

暂无评论

推荐阅读
TEZNKK3IfmPf