【设计模式】建造者模式

建造者模式的意图

建造者模式又被称呼为生成器模式,属于创建型模式。(使用多个简单对象一步一步构建成一个复杂的对象,这样像一间房子从地基到建造完成,这就是为啥被称呼为叫做建造者模式的原因吧!,而且一般来说房主是不需要了解建造过程和细节的,只需要知道所需房子的类型和内容即可,其他由建造者来补充实现,就可以获得一个复杂的房子)

意图将一个复杂对象的构建和它的表示分离,使得同样的创建过程可以创建不同的表示。

  • 它将客户端与包含多个组成部分(或部件)的复杂对象的创建过程进行分离,客户端无需知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。它关注如何一步一步创建一个的复杂对象,不同的具体建造者定义了不同的创建过程,且具体建造者互相独立,增加新的建造者非常方便,无需修改已有代码,这样系统会具有良好的扩展性。

解决什么问题

(1)、方便用户创建复杂的对象(不需要知道实现过程)
(2)、代码复用性&封装性(将对象构建过程和细节进行封装&复用)

结构图

  • 抽象建造者(builder):描述具体建造者的公共接口,一般用来定义建造细节的方法,并不涉及具体的对象部件的创建。

  • 具体建造者(ConcreteBuilder):描述具体建造者,并实现抽象建造者公共接口。

  • 指挥者(Director):调用具体建造者来创建复杂对象(产品)的各个部分,并按照一定顺序(流程)来建造复杂对象。

  • 产品(Product):描述一个由一系列部件组成较为复杂的对象。

应用实例

(找的设计模式的一个作业)

Sunny软件公司欲开发一个视频播放软件,为了给用户使用提供方便,该播放软件提供多种界面显示模式,如完整模式、精简模式、记忆模式、网络模式等。在不同的显示模式下主界面的组成元素有所差异,如在完整模式下将显示菜单、播放列表、主窗口、控制条等,在精简模式下只显示主窗口和控制条,而在记忆模式下将显示主窗口、控制条、收藏列表等。尝试使用建造者模式设计该软件。

// 角色类:复杂产品,考虑到代码的可读性,真实情况下,有些成员属性的类型需要自定义

public class Element {
//    Displays menus, playlists, main windows, control bars

    private String displaysMenus;
    private String playlists;
    private String mainWindows;
    private String controlBars;
    private String favoritesList;

    public Element() {
    }

    public Element(String displaysMenus, String playlists, String mainWindows, String controlBars, String favoritesList) {
        this.displaysMenus = displaysMenus;
        this.playlists = playlists;
        this.mainWindows = mainWindows;
        this.controlBars = controlBars;
        this.favoritesList = favoritesList;
    }

    public String getDisplaysMenus() {
        return displaysMenus;
    }

    public void setDisplaysMenus(String displaysMenus) {
        displaysMenus = displaysMenus;
    }

    public String getPlaylists() {
        return playlists;
    }

    public void setPlaylists(String playlists) {
        this.playlists = playlists;
    }

    public String getMainWindows() {
        return mainWindows;
    }

    public void setMainWindows(String mainWindows) {
        this.mainWindows = mainWindows;
    }

    public String getControlBars() {
        return controlBars;
    }

    public void setControlBars(String controlBars) {
        this.controlBars = controlBars;
    }

    public String getFavoritesList() {
        return favoritesList;
    }

    public void setFavoritesList(String favoritesList) {
        this.favoritesList = favoritesList;
    }

    @Override
    public String toString() {
        return "Element{" +
                "displaysMenus='" + displaysMenus + '\'' +
                ", playlists='" + playlists + '\'' +
                ", mainWindows='" + mainWindows + '\'' +
                ", controlBars='" + controlBars + '\'' +
                ", favoritesList='" + favoritesList + '\'' +
                '}';
    }
}

角色建造起:抽象建造者

/**
 * 显示模式建造
 */
abstract class ElementBuilder {
    protected Element element = new Element();

    /**
     *显示菜单
     */
    public abstract void buildDisplaysMenus();

    /**
     * 播放列表
     */
    public abstract void buildPlayLists();

    /**
     * 主窗口
     */
    public abstract void buildMainWindows();

    /**
     * 控制条
     */
    public abstract void buildControlBars();

    /**
     * 收藏列表
     */
    public abstract void buildFavoritesList();

    /**
     * 创建显示模式
     * @return 模式组成元素
     */
    public Element createElement(){
        return element;
    }
}

具体建造者

具体建造者
/**
 * 记忆模式建造者
 * @author haoyang
 */
public class MemoryMode extends ElementBuilder{


    @Override
    public void buildDisplaysMenus() {

    }

    @Override
    public void buildPlayLists() {

    }

    @Override
    public void buildMainWindows() {
        element.setMainWindows("主窗口");
    }

    @Override
    public void buildControlBars() {
        element.setControlBars("控制条");
    }

    @Override
    public void buildFavoritesList() {
        element.setFavoritesList("收藏列表");
    }

    @Override
    public Element createElement() {
        return super.createElement();
    }
}
/**
 * 完整模式建造者
 * @author haoyang
 */
public class CompleteMode extends ElementBuilder{
    @Override
    public void buildDisplaysMenus() {
        element.setDisplaysMenus("显示菜单");
    }

    @Override
    public void buildPlayLists() {
        element.setPlaylists("播放列表");
    }

    @Override
    public void buildMainWindows() {
        element.setMainWindows("主窗口");
    }

    @Override
    public void buildControlBars() {
        element.setControlBars("控制条");
    }

    @Override
    public void buildFavoritesList() {

    }

    @Override
    public Element createElement() {
        return super.createElement();
    }

}
/**
 * 精简模式建造者
 * @author haoyang
 */
public class LiteMode extends ElementBuilder{


    @Override
    public void buildDisplaysMenus() {

    }

    @Override
    public void buildPlayLists() {

    }

    @Override
    public void buildMainWindows() {
        element.setMainWindows("主窗口");
    }

    @Override
    public void buildControlBars() {
        element.setControlBars("控制条");
    }

    @Override
    public void buildFavoritesList() {

    }

    @Override
    public Element createElement() {
        return super.createElement();
    }

}

指挥者,指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类

/**
 * 指挥者,指导具体构建者如何构建产品,控制调用先后次序,并向调用者返回完整的产品类
 * @author haoyang
 */
public class VideoPlayback {

    private final ElementBuilder builder;

    public VideoPlayback(ElementBuilder builder) {
        this.builder = builder;
    }

    public Element build(){
        builder.buildDisplaysMenus();
        builder.buildPlayLists();
        builder.buildMainWindows();
        builder.buildControlBars();
        builder.buildFavoritesList();
        return builder.createElement();
    }
}

测试类

public class Main {
    public static void main(String[] args) {

        ElementBuilder builder1 = new MemoryMode();
        ElementBuilder builder2 = new CompleteMode();
        ElementBuilder builder3 = new LiteMode();
        //记忆模式
        VideoPlayback vp = new VideoPlayback(builder1);
        //完整模式
        VideoPlayback vp2 = new VideoPlayback(builder2);
        //精简模式
        VideoPlayback vp3 = new VideoPlayback(builder3);
        System.out.println(vp2.build());
        System.out.println(vp.build());
        System.out.println(vp3.build());
    }
}

优缺点

1、优点

(1)、每一个具体建造者都相对独立,而且和其他的具体建造者无关,因此可以很方便地替换具体建造者或者增加新地具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
(2)、增加新的具体建造者无需修改原有类库的代码,易于扩展,符合“开闭原则”。
(3)、将复杂的产品创建步骤分解在不同的方法中,使得创建过程更加清晰,更加方便使用程序来控制创建过程。
(4)、客户端不需要知道产品内部细节,可以将产品的建造和表示进行分离,实现解耦,相同的创建过程可以创建不同的产品对象。

2、缺点

(1)、创建的产品一般具有较多的共同点,组成部分相似,如果产品直接的差异性很大,例如很多组成部分都不相同,就不适合,限制了使用的范围
(2)、内部变化复杂的话,就需要定义很多具体建造者来实现变化,这会导致系统变得庞大,增加理解难度以及运行成本,难以维护

使用时需要注意什么?

  • 了解完大概这些,其实和工厂模式很相似,但是有区别:建造者模式更加关注与零件装配的顺序,一般用来构建更加复杂的对象
  • 在建造者模式的定义中提到了复杂对象,那么什么是复杂对象?简单来说,复杂对象是指那些包含多个成员属性的对象,这些成员属性也称为部件或零件,如汽车包括方向盘、发动机、轮胎等部件,电子邮件包括发件人、收件人、主题、内容、附件等部件。

适用场景(看看菜鸟教程https://www.runoob.com/design-pattern/builder-pattern.html)

  • 一般来说,使用建造者模式需要包含多个成员属性,而且属性直接相互依赖,需要指定其生成的顺序,具备共性
  • 适用于一个具有较多的零件(属性)的产品(对象)的创建过程。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
posted @ 2022-10-29 20:05  雨季悠理  阅读(116)  评论(0编辑  收藏  举报