一段对话讲完建造者模式

截止今天,小秋学习Java刚刚满三个月。此刻的小秋感觉自己Java学的还不错,想去帅地面前炫耀一番,于是,就发生了一下一番对话…..

得意的小秋

帅地:嗨,小秋,看你今天气色不错啊。最近Java学的怎么样了?

小秋:说实话,比起三个月前我学指针的那段日子,这Java太友好了,感觉就是分分种的事(暗自得意)。

帅地:我靠,你这口气还挺大啊。从c的面向过程到Java的面向对象,还习惯不?

小秋:哎,还行,无非就是“一切皆对象”,Java中的对象感觉类似于C中的结构体。反正不过三七二十一,我脑子里都把他们当成是一个对象就得了。(内心自我感觉良好)

帅地:看你也学了三个月了,要不我随便拿道题考考你?(让你不谦虚,暗自偷笑)

小秋:好啊,正好练练手(嘿嘿,终于可以展现实力了)。

重载多次的构造函数

帅地:假如有一个蛋糕Cake对象,蛋糕这个对象有一个必选属性size,还有一些可选属性apple,banana,orange,mango等,必选属性代表用户必须要指定蛋糕的大小,可选属性代表这些蛋糕要加哪些材料。

小秋:这个很简单啊,创建一个Cake类,里面有size,apple,banana,orange,mango属性,然后构造器的参数里指定size这个参数就可以了。我直接上代码吧:

public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;
    //new时必须给出size
    public Cake(int size) {
        this.size = size;
    }
}

帅地:可选参数呢?我要new一个size=30,并且添加apple的蛋糕怎么办?

小秋:哦,我写的太快,忘了重载了,稍等(心想,这还不简单)。

public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;

    public Cake(int size) {
        this.size = size;
    }
    public Cake(int size, String apple) {
        this.size = size;
        this.apple = apple;
    }
    public Cake(int size, String apple, String orange) {
        this.size = size;
        this.apple = apple;
        this.orange = orange;
    }
    public Cake(int size, String apple, String orange, String mango) {
        this.size = size;
        this.apple = apple;
        this.orange = orange;
        this.mango = mango;
    }
}

小秋:这下总可以了吧,你要加哪些料,你就使用哪个构造器。全部给你重载了。

帅地:(露出狡猾的表情)写构造函数倒是挺快的,那如果我要只加apple和mango的蛋糕呢?

小秋:啊?好吧,你这是逼我把所有组合的构造器都写出来。

于是,小秋把所有构造器的组合都写了出来。由于size是个必须参数,把其他四个可选参数进行组合,一共有16种。

噼里啪啦,劈里啪啦,小秋一口气把他们全部写出来了

public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;

    public Cake(int size){
        this.size = size;
    }
    public Cake(int size, String apple){
        this.size = size;
        this.apple = apple;
    }
    public Cake(int size, String banana){
        this.size = size;
        this.banana = banana;
    }
    .....
}

小秋:好了,这下,你要啥组合有啥组合了。

帅地:四个可选参数你就写了这么一大堆参数了。确定这样写?

小秋:我觉得挺好的啊,反正很快,多写几个就多写几个吧。

帅地:那如果给你6个可选参数呢?

这时候小秋偷偷算了一些,发现一共有74种组合?

小秋:不就是74种组合,我觉得问题不是很大(心有点虚)。

帅地:那万一有10个可选参数呢?

小秋:…..

帅地:而且你重载那么多构造器,用户在在new的时候,第一个参数和第二个参数代表什么,用户混乱了怎么吧?例如,你有个apple+banana的构造器

public Cake(int size, String apple, String banana){
    this.size = size;
    this.apple = apple;
    this.banana = banana;
}

但是用户在new的时候,可能忘记了参数的顺序

Cake cake = new Cake(size,“banana”,“apple”)。

小秋:我会提供相应的文档啊,忘记了可以看文档勒。

帅地:几百个构造函数,而且还那么相似,你去看下文档试试,然后说说你的心情。

小秋:……(不知所措)。

通过Javabean的模式

帅地:有没其他什么办法?

小秋:我想到另一种办法了,我可以通过set和get方法来设置可选参数的。我直接上代码你看看

public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;

    public Cake(int size) {
        this.size = size;
    }
    //通过set来添加材料
    public void setApple(String apple) {
        this.apple = apple;
    }

    public void setBanana(String banana) {
        this.banana = banana;
    }

    public void setMango(String mango) {
        this.mango = mango;
    }

    public void setOrange(String orange) {
        this.orange = orange;
    }
}

此时的小秋有点得意….

帅地:挺不错,这种方法比刚才的好多了,又简洁。

此时如果要new一个apple+orange+mango的蛋糕的话,代码如下:

Cake cake = new Cake(30);
cake.setApple("apple");
cake.setOrange("orange");
cake.setMange("mange");
参数依赖检查问题

帅地:这种方法也是有缺点,例如用构造器重载时一行代码就可以搞定了,现在要用四行代码。

小秋:反正我觉得这样很nice(得意中…)。

帅地:不过这样写有一个致命的缺点,假如那些属性之间存在依赖性的话,怎么办?例如Cake多了A,B两个属性,并且这两个属性之间存在依赖关系。如果你设置了属性A,但是没有设置属性B,那么这个Cake对象就会出问题。或者属性的先后顺序设置也可能会导致出现问题。对于这种情况,你在什么地方检查这种相互依赖的逻辑?

小秋:有点蒙蔽,不知所措….。

小秋:那你说怎么办?

静态内部类

帅地:其实你已经做的相当不错了,不过我今天就教你另外一个办法,我们可以开放一个静态内部类专门用来与外界打交道,用来收集用户想要设置的属性并且做检查。直接上代码:

public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;
    //private,让外面无法直接创建
    private Cake(Builer builer) {
        this.size = builer.size;
        this.apple = builer.apple;
        .....
    }
    //专门用来与外界打交道
    public static class Builer {
        private int size;
        private String apple;
        private String banana;
        private String orange;
        private String mango;
        public void setSize(int size) {
            this.size = size;
        }
        //为了省点代码,其他的省略
        public Cake build() {
            //检查参数之间的依赖关系是否正确
            return new Cake(this);
        }
        .....
    }
}

假如我要new一个apple+orange的Cake

Cake.Builer builer = new Cake.Builer();
builer.setSize(30);
builer.setApple("apple");
builer.setOrange("orange");
//创建一个蛋糕
Cake cake = builer.build();

帅地:这种方法牛吧?这还不够,我们还可以采用链式调用的方法。

链式调用
public class Cake {
    private int size;
    private String apple;
    private String banana;
    private String orange;
    private String mango;
    //private,让外面无法直接创建
    private Cake(Builer builer) {
        this.size = builer.size;
        this.apple = builer.apple;
        .....
    }
    //专门用来与外界打交道
    public static class Builer {
        private int size;
        private String apple;
        private String banana;
        private String orange;
        private String mango;
        //返回参数改为Builer
        public Builer setSize(int size) {
            this.size = size;
            return this;
        }

        public Builer setApple(String apple) {
            this.apple = apple;
            return this;
        }
        //为了省点代码,其他的省略
        public Cake build() {
            //检查参数之间的依赖关系是否正确
            return new Cake(this);
        }
    }
}

如何使用?

Cake cake = new Cake.Builer()
            .setSize(30)
            .setApple("apple")
            .setOrange("orange")
            .build();

一行代码就搞定了。

帅地:厉害吧?

小秋:涨知识了,看来我还是太年轻了,以后得好好向帅地学习。

建造者模式

帅地:其实,上面那种方法算是23种设计模式中的其中一种—-建造者模式。不过这只是一个简化版的建造者模式。

对于建造者模式,具体的UML图是这样的:

在这个UML图中,Builder是一个接口,定义一套规范,而我们使用的例子中,没有使用接口,直接使用具体类,但核心思想还是一样的。

其核心思想就是:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

小秋:哇,强啊。我要给你点赞…..

算是第二次采取对话的方式写….,以后会多采取这种方式来写勒。

关注公我的众号:苦逼的码农,获取更多原创文章,后台回复礼包送你一份时下热门的资源大礼包。同时也感谢把文章介绍给更多需要的人

?

原文地址:https://www.cnblogs.com/kubidemanong/p/9650964.html

时间: 2024-10-18 08:21:36

一段对话讲完建造者模式的相关文章

第七讲:建造者模式

Product:House Builder:HouseBuilder(工程队) ConcreteBuilder:PingFangBuilder.GongyuBuilder Director:组合的模式,包含Builder,包含工程队,由Director来指使工程队做事.组合不是聚合,Director包含了Builder. construct()是建造方法,不是构造函数.就是Director的makeHouse()方法. 演变的过程:自己做->工程队做->设计师做. 客户端代码越来越少越来越简洁

Android设计模式--建造者模式

回头看自己写的东西,在关于Android自定义控件时,写的代码适用性比较高,但是看上去没有什么技术含量,所以在学习设计模式的时候,想想有些东西是否能够改进,比如说: 自定义Dialog是Android应用必须的,系统的控件实在是太难看了: 在构建中,完全是,new完对象之后,需要什么构建什么,这样写没有问题,可读性也还行,就是看上去不咋的. 以下是小部分代码片段: package com.example.demo.Builder; /** * * @author qubian * @data 2

建造者模式及应用举例

目录 模式名和分类 意图 动机 适用性 结构 参与者 协作 效果 代码实例 已知应用 总结 模式名和分类 builder 创建型模式 意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 将对象的创建过程细化并固化,能依此创建一个流水线,在流水线上组装对象的各个零件,最终生成我们想要的对象 动机 spring创建对象时,我们在解析xml文件和一些系统配置来创建一个的BeanDefinition,解析过程是复杂且多样的. 如果准备好所有的参数,并在new的时候直接赋值进

建造者模式(Builder)——从组装电脑开始

建造者模式(Builder)--从组装电脑开始 建造者模式概括起来就是将不同独立的组件按照一定的条件组合起来构成一个相对业务完整的对象.调用者无需知道构造的过程. 我们从组装电脑开始 让我们从买组装电脑开始吧. 首先要买一个电脑,一般都有两个选择 -- 品牌电脑和组装电脑,一般人为了省事和放心都会选择买品牌电脑(也就是整机).在这里,为了更好的分析问题,假定我们为了性价比决定要买组装电脑.那么我们该怎么做呢. 首先我们得学习一个完整的电脑的组成部分有哪些? 经过翻查一部分资料发现,主要部件分为主

java/android 设计模式学习笔记(10)---建造者模式

这篇博客我们来介绍一下建造者模式(Builder Pattern),建造者模式又被称为生成器模式,是创造性模式之一,与工厂方法模式和抽象工厂模式不同,后两者的目的是为了实现多态性,而 Builder 模式的目的则是为了将对象的构建与展示分离.Builder 模式是一步一步创建一个复杂对象的创建型模式,它允许用户在不知道内部构建细节的情况下,可以更精细地控制对象的构造流程.一个复杂的对象有大量的组成部分,比如汽车它有车轮.方向盘.发动机.以及各种各样的小零件,要将这些部件装配成一辆汽车,这个装配过

建造者模式(Builder)

定义 (本人在阅读完本书的中英两个版本之后发现对建造者模式十窍懂了九窍,所以直接去网上搜别人的分析了,所以本章大部分是根据网上的资料收集来的,此外,代码例子表示本书的例子不合适,也换了,所以本章和这本书关系不大.) 建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.建造者模式最重要的两个角色:抽象建造者(Builder)和指导者(Director),其中建造者知道怎么(How)去建造产品,而指导者知道去制造什么(What)产品,建造者模式用建房子的例子来说明

创建型模式(六)建造者模式

介绍这个设计模式之前,我先说两个知识点.Is-a.Has-a. Is-a 指一个类是另一个类的一种,是属于关系. Has-a 指表示一个角色的一项责任. 一句话的概要 创建一个复杂的对象,让其由各部分子对象通过一定的步骤而组合而成.这就是建造者模式. 剧情 小明跟女神交往过程中,总是感觉进展缓慢.于是小明就决定用一个烛光晚餐的惊喜,来打动女神. 但是,小明就一个人,他白天要约女神出来.所以他准备雇佣一个人来进行烛光晚餐的准备. 剧情看着很简单,但是我们来分析一下,怎么构造这种场景. 首先,必要的

好菜每回味不同—建造者模式

<大话设计模式>中讲建造者模式(Builder Pattern)引用一个例子:麦当劳.肯德基的汉堡不管在哪家店里吃,什么时间时间去吃,至少在中国,味道基本都是一样.而那道“鱼香肉丝”几乎是所有大小中餐馆饭店都有的一道菜,但却可以吃出万种口味来,这是为什么呢? 建造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式(Builder Pattern)结构图 Builder是为了创建一个Product对象的各个部件指定的抽

设计模式(五) : 创建型模式--建造者模式

建造者模式的意图是将产品的内部表象和产品的生产过程分割开来. 类图: 示意性代码: package com.javadesignpattern.builder; public interface Builder { public void buildPart1(); public void buildPart2(); public Product retrieveProduct(); } ? 1 2 3 4 5 6 7 package com.javadesignpattern.builder;