设计模式系列--23种常见设计模式之建造者模式(13)

建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

一般会定义一个公共的抽象建造者,定义了具体需要建造哪些部分;

设置具体的执行者,构建建造过程,顺序等;

定义抽象的公共出的产品对象,提取通用的属性。

实现过程:按需获取或创建对应的具体建造器,执行者执行构造过程,获取生产的结果。

如下:

定义一个建造者:

package cn.pers.sample.build;

/**
 * 定义的抽象构建者
 * @author WeiSong <br>
 * @since 0.0.1
 * 2021/1/28 16:59
 */
public abstract class Builder {

    protected House house = new House();

    abstract void buildBasic();

    abstract void buildOut();

    abstract void buildInner();

    abstract void buildTop();

    House getHouse() {
        return house;
    }

}

定义执行过程:

package cn.pers.sample.build;

/**
 * 构建执行过程
 */
class Director {
    private Builder builder;


    public Director(Builder builder) {
        this.builder = builder;

    }

    public void setBuilder(Builder builder) {
        this.builder = builder;

    }

    //产品构建与组装方法
    public House construct() {

        builder.buildBasic();
        builder.buildInner();
        builder.buildOut();
        builder.buildTop();

        return builder.getHouse();

    }

}

定义抽象对象:

package cn.pers.sample.build;

import lombok.Data;

/**
 * 抽象产品
 * @author WeiSong <br>
 * @since 0.0.1
 * 2021/1/28 16:48
 */
//@Builder
@Data
public class House {

    private String basic;
    private String out;
    private String inner;
    private String top;

}

分别构建实现两个具体的建造者:大房子和平房

package cn.pers.sample.build;

/**
 * @author WeiSong <br>
 * @since 0.0.1
 * 2021/1/28 17:04
 */
public class LowHouseBuilder extends Builder {
    @Override
    void buildBasic() {
        house.setBasic("构建平房地基完成");
    }

    @Override
    void buildOut() {
        house.setOut("构建平房外立面完成");
    }

    @Override
    void buildInner() {
        house.setInner("构建平房装修完成");
    }

    @Override
    void buildTop() {
        house.setTop("构建平房顶完成");

    }
}
package cn.pers.sample.build;

/**
 * @author WeiSong <br>
 * @since 0.0.1
 * 2021/1/28 17:04
 */
public class TopHouseBuilder extends Builder {
    @Override
    void buildBasic() {
        house.setBasic("构建大房子地基完成");
    }

    @Override
    void buildOut() {
        house.setOut("构建大房子外立面完成");
    }

    @Override
    void buildInner() {
        house.setInner("构建大房子装修完成");
    }

    @Override
    void buildTop() {
        house.setTop("构建大房子顶完成");

    }
}

执行最后的生产:

package cn.pers.sample.build;

/**
 * @author WeiSong <br>
 * @since 0.0.1
 * 2021/1/28 17:03
 */
public class MainTest {

    public static void main(String[] args) {

        //这里具体可以配置 或者反射等方式根据需要获取对应的建造者
        Builder  builder = new TopHouseBuilder();
        Director director = new  Director(builder);
        final House topHouse = director.construct();
        System.out.println(topHouse.toString());

        Builder  builder1 = new LowHouseBuilder();
        Director director1 = new  Director(builder1);
        final House lowHouse = director1.construct();
        System.out.println(lowHouse.toString());


    }
}

结果:

House(basic=构建大房子地基完成, out=构建大房子外立面完成, inner=构建大房子装修完成, top=构建大房子顶完成)
House(basic=构建平房地基完成, out=构建平房外立面完成, inner=构建平房装修完成, top=构建平房顶完成)

注意:扩展阅读

代码中 House中有个注释掉的 //@Builder 用过lombok的都知道这个其实就是个构造者模式,我们加上这个注解后看.class的反编译文件

package cn.pers.sample.build;

public class House
{
    private String basic;
    private String out;
    private String inner;
    private String top;
    
    House(final String basic, final String out, final String inner, final String top) {
        this.basic = basic;
        this.out = out;
        this.inner = inner;
        this.top = top;
    }
    
    public static HouseBuilder builder() {
        return new HouseBuilder();
    }
    
    public String getBasic() {
        return this.basic;
    }
    
    public String getOut() {
        return this.out;
    }
    
    public String getInner() {
        return this.inner;
    }
    
    public String getTop() {
        return this.top;
    }
    
    public void setBasic(final String basic) {
        this.basic = basic;
    }
    
    public void setOut(final String out) {
        this.out = out;
    }
    
    public void setInner(final String inner) {
        this.inner = inner;
    }
    
    public void setTop(final String top) {
        this.top = top;
    }
    
    @Override
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        }
        if (!(o instanceof House)) {
            return false;
        }
        final House other = (House)o;
        if (!other.canEqual(this)) {
            return false;
        }
        final Object this$basic = this.getBasic();
        final Object other$basic = other.getBasic();
        Label_0065: {
            if (this$basic == null) {
                if (other$basic == null) {
                    break Label_0065;
                }
            }
            else if (this$basic.equals(other$basic)) {
                break Label_0065;
            }
            return false;
        }
        final Object this$out = this.getOut();
        final Object other$out = other.getOut();
        Label_0102: {
            if (this$out == null) {
                if (other$out == null) {
                    break Label_0102;
                }
            }
            else if (this$out.equals(other$out)) {
                break Label_0102;
            }
            return false;
        }
        final Object this$inner = this.getInner();
        final Object other$inner = other.getInner();
        Label_0139: {
            if (this$inner == null) {
                if (other$inner == null) {
                    break Label_0139;
                }
            }
            else if (this$inner.equals(other$inner)) {
                break Label_0139;
            }
            return false;
        }
        final Object this$top = this.getTop();
        final Object other$top = other.getTop();
        if (this$top == null) {
            if (other$top == null) {
                return true;
            }
        }
        else if (this$top.equals(other$top)) {
            return true;
        }
        return false;
    }
    
    protected boolean canEqual(final Object other) {
        return other instanceof House;
    }
    
    @Override
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final Object $basic = this.getBasic();
        result = result * 59 + (($basic == null) ? 43 : $basic.hashCode());
        final Object $out = this.getOut();
        result = result * 59 + (($out == null) ? 43 : $out.hashCode());
        final Object $inner = this.getInner();
        result = result * 59 + (($inner == null) ? 43 : $inner.hashCode());
        final Object $top = this.getTop();
        result = result * 59 + (($top == null) ? 43 : $top.hashCode());
        return result;
    }
    
    @Override
    public String toString() {
        return "House(basic=" + this.getBasic() + ", out=" + this.getOut() + ", inner=" + this.getInner() + ", top=" + this.getTop() + ")";
    }
    
    public static class HouseBuilder
    {
        private String basic;
        private String out;
        private String inner;
        private String top;
        
        HouseBuilder() {
        }
        
        public HouseBuilder basic(final String basic) {
            this.basic = basic;
            return this;
        }
        
        public HouseBuilder out(final String out) {
            this.out = out;
            return this;
        }
        
        public HouseBuilder inner(final String inner) {
            this.inner = inner;
            return this;
        }
        
        public HouseBuilder top(final String top) {
            this.top = top;
            return this;
        }
        
        public House build() {
            return new House(this.basic, this.out, this.inner, this.top);
        }
        
        @Override
        public String toString() {
            return "House.HouseBuilder(basic=" + this.basic + ", out=" + this.out + ", inner=" + this.inner + ", top=" + this.top + ")";
        }
    }
}

反编译后查看,里面有个静态类,HouseBuilder ,内部就是一个构建的过程,他和我们这里说的建造者模式是不同的,他是一种以构建的方式来构建对象的过程,可以不对外暴漏set方法,直接以build的方式来构建。比如:House house = House.builder().basic("地基").out("外立面").build();

总结:

1.主要优点

(1) 在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
(2) 每一个具体建造者没有关联,按需索取具体需要的建造者,即可得到不同的产品对象。
(3) 由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合“开闭原则”
(4) 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。

2.主要缺点

(1) 产品要求具有较多的共同点,其组成部分相似,如果差异性很大,不适合使用建造者模式,比如房子和汽车。
(2) 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。

3.适用场景
(1) 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
(2) 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
(3) 对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
(4) 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

猜你喜欢

转载自blog.csdn.net/weisong530624687/article/details/113352255