Java大话设计模式学习总结(十三)---建造者模式

建造者模式(Builder),将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
Java大话设计模式学习总结(十三)---建造者模式_第1张图片
使用建造者模式的情景:
主要是用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。

建造者模式的好处就是使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

举例:
当玩一个角色扮演类的游戏时,通常都需要创建一个角色,可以选择男性或女性,生成人物的打扮和武器也会根据选择的性别发生变化,但是男性和女性单独创建的流程都是固定不变的,即所有男性的打扮、武器都是固定的,这个生成角色的过程就可以用建造者模式实现。代码如下:

// Builder接口,用来定义构造对象需要的全部流程,并且有一个返回组装好的对象的方法
public interface IBuilder {
    public void buildSex();
    public void buildCloth();
    public void buildWeapon(); 
    public Person createPerson();
}

// 构建男性角色的类
public class BuildMan implements IBuilder {

    Person person;

    public BuildMan() {
        this.person = new Person();
    }

    @Override
    public void buildSex() {
        person.setSex("男");
        System.out.println("已选择男性角色进行创建");
    }

    @Override
    public void buildCloth() {
        person.setCloth("男性服饰");
        System.out.println("创建男性角色服装");
    }

    @Override
    public void buildWeapon() {
        person.setWeapon("男性武器");
        System.out.println("创建男性角色武器");
    }

    @Override
    public Person createPerson() {
        return this.person;
    }

}

// 构建女性角色的类
public class BuildWomen implements IBuilder {

    Person person;
    
    public BuildWomen() {
        this.person = new Person();
    }
    
    @Override
    public void buildSex() {
        person.setSex("女");
        System.out.println("已选择女性角色进行创建");
    }

    @Override
    public void buildCloth() {
        person.setCloth("女性服装");
       System.out.println("创建女性角色服装");
    }

    @Override
    public void buildWeapon() {
        person.setWeapon("女性武器");
        System.out.println("创建女性角色武器");
    }

    @Override
    public Person createPerson() {
        return this.person;
    }

}

// 角色类
public class Person {
    private String sex;
    private String cloth;
    private String weapon;
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public String getCloth() {
        return cloth;
    }
    public void setCloth(String cloth) {
        this.cloth = cloth;
    }
    public String getWeapon() {
        return weapon;
    }
    public void setWeapon(String weapon) {
        this.weapon = weapon;
    }
    public String show(){
        return "角色性别:" + sex + " 角色服饰:" + cloth + " 角色武器:" + weapon;
    }
}

是不是有的朋友会问,现在不是可以直接创建对象了吗?代码如下:

public class Test {
    public static void main(String[] args) {
        // 创建一个男性角色
        BuildMan man = new BuildMan();
        man.buildSex();
        man.buildCloth();
        man.buildWeapon();
        Person person1 = man.createPerson();
        System.out.println(person1.show());

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

        BuildWomen woman = new BuildWomen();
        woman.buildSex();
        woman.buildCloth();
        woman.buildWeapon();
        Person person2 = woman.createPerson();
        System.out.println(person2.show());
    }
}

仔细观察,所有生成角色的业务逻辑是一样的,必须要设置性别、服装和武器,少设置一个就会不符合业务逻辑。建造者模式就是把构造的流程放到一个专门指挥角色生成的对象中,由他负责去生成相应的属性,这样可以避免忘记生成某个属性,导致错误出现。下面添加这个指挥者类:

public class BuildDerector {
    public void BuildPerson(IBuilder builder) {
        builder.buildSex();
        builder.buildCloth();
        builder.buildWeapon();
    }
}

指挥者类只负责加工每个对象,不负责其他的业务逻辑。
下面看主程序类:

public class Test {
    public static void main(String[] args) {
        // 创建一个男性角色
        BuildDerector buildDerector = new BuildDerector();
        
        BuildMan man = new BuildMan();
        buildDerector.BuildPerson(man);
        Person person1 = man.createPerson();
        System.out.println(person1.show());
        
        System.out.println("============");
        
        BuildWomen woman = new BuildWomen();
        buildDerector.BuildPerson(woman);
        Person person2 = woman.createPerson();
        System.out.println(person2.show());
    }
}

结果如下:

已选择男性角色进行创建
创建男性角色服装
创建男性角色武器
角色性别:男 角色服饰:男性服饰 角色武器:男性武器
============
已选择女性角色进行创建
创建女性角色服装
创建女性角色武器
角色性别:女 角色服饰:女性服装 角色武器:女性武器

刚开始看的时候,我觉得建造者模式和模板模式十分相似,都是按照一个模板去实现业务逻辑,下面拿出来模板模式的主要代码:

// 体育运动模板类
public abstract class Sports {

    public void start(){
        System.out.println("比赛开始,开始计时。");
    }
    
    public void end(){
        System.out.println("时间到,比赛结束。");
    }
    
    public abstract void process();
    
    // 使用final修饰,防止修改模板
    public final void play(){
        start();
        process();
        end();
    }
}

public class Basketball extends Sports {
    @Override
    public void process() {
        System.out.println("开始进行篮球比赛");
    }
}

public class Test {
    public static void main(String[] args) {
        Sports sports = new Basketball();
        sports.play();
        System.out.println("=== another sport game ===");
        sports = new Football();
        sports.play();
    }
}

可以看出来,模板模式执行的业务逻辑都定义在了父类当中,所以每个子类都需要按照这个流程去执行。而建造者模式,虽然本次例子中,都是由同一个指挥者去执行,但指挥者类可以扩展出来子类,根据不同子类的建造者,采用不同的策略去执行,并且能保证同一个建造者实例化的对象执行的业务逻辑都相同,但是不同类的建造者实例化的对象执行的业务逻辑可以不相同

模板模式的使用情景:
每个子类的业务逻辑基本一样;很多代码可以进行复用;进行系统维护升级的情况下,可以采用模板模式进行向下兼容,通过增加钩子判断相应的版本以及执行的流程。

建造者模式的使用场景:
很多子类都需要执行相同的方法,但是存在顺序、逻辑不完全相同的情况

你可能感兴趣的:(设计模式)