初识建造者模式
建造者模式实际上是常用的设计模式。顾名思义,builder的意思是建造者或者建筑工人,谈到建造自然会想到楼房。楼房是千差万别的,楼房的外形、层数、内部房间的数量、房间的装饰等等都不一样,但是对于建造者来说,抽象出来的建筑流程是确定的,往往建筑一座楼房包括下面的步骤:
(1)打桩,建立基础
(2)建立框架等。建造者模式的本质和建造楼房是一致的:即流程不变,但每个流程实现的具体细节则是经常变化的。建造者模式的好处就是保证了流程不会变化,流程即不会增加、也不会遗漏或者产生流程次序错误,这是非常重要的。我们熟知的楼歪歪事件,官方的解释就是由于先建立楼房后,再建设停车场造成的,这是典型的建造次序错乱。(看来这些人儿不知道建造者模式啊!!!)
我生活的地方有一个菜叫“锅包肉”。基本每个餐馆都有,但是每个餐馆的味道都不一样,原因是什么呢?因为这道菜的作法没有形成标准呗!每个人的作法都不一样,所以味道就不一样了。这实际上通过“建造者模式”让每个馆子的“锅包肉”都一样。同样的KFC做出来的东西,不论是全国哪家店做出来就都一个味,因为KFC内部有很严格的规定,做巨无霸有做巨无霸的流程,必须严格遵守,这样做出来的东西当然一致了。KFC就是采用了建造者模式!!
下面讲下日常开发中,用到得builder模式.
builder模式也叫建造者模式,builder模式的作用将一个复杂对象的构建与他的表示分离,使用者可以一步一步的构建一个比较复杂的对象。示例如下:
public static void main(String[] args) {
MetaVo metaVo = new MetaVo();
metaVo.setIcon("1")
.setTitle("2")
.setNoCache(true);
System.out.println(metaVo);
}
这种设计模式的精髓就主要有两点:其一,用户使用简单,并且可以在不需要知道内部构建细节的情况下,就可以构建出复杂的对象模型;其二,对于设计者来说,这是一个解耦的过程,这种设计模式可以将构建的过程和具体的表示分离开来。
Builder 模式创建步骤:
- 在类中,创建一个静态内部类,包含外部类的全部属性;
- 在内部类中,为每一个属性进行赋值;
- 内部类中创建 build 方法,返回外部类对象
- 在外部类中创建静态 builder方法,返回内部类对象
拿实体类举例就是创建一个实体类,然后呢,将你的set方法稍作改动,示例如下(已注释说明):
package com.pmtest.system.domain.vo;
import com.pmtest.common.utils.StringUtils;
/**
* 路由显示信息
*
* @author ppq
*/
public class MetaVo
{
/**
* 设置该路由在侧边栏和面包屑中展示的名字
*/
private String title;
/**
* 设置该路由的图标,对应路径src/assets/icons/svg
*/
private String icon;
/**
* 设置为true,则不会被 <keep-alive>缓存
*/
private boolean noCache;
/**
* 内链地址(http(s)://开头)
*/
private String link;
public MetaVo()
{
}
public MetaVo(String title, String icon)
{
this.title = title;
this.icon = icon;
}
public MetaVo(String title, String icon, boolean noCache)
{
this.title = title;
this.icon = icon;
this.noCache = noCache;
}
public MetaVo(String title, String icon, String link)
{
this.title = title;
this.icon = icon;
this.link = link;
}
public MetaVo(String title, String icon, boolean noCache, String link)
{
this.title = title;
this.icon = icon;
this.noCache = noCache;
if (StringUtils.ishttp(link))
{
this.link = link;
}
}
public boolean isNoCache()
{
return noCache;
}
//默认生成类型是void,将其修改为你的实体类名称,注意不要使用你的属性的修饰类型
public MetaVo setNoCache(boolean noCache)
{
this.noCache = noCache;
//然后在加上这个return this;结束
return this;
}
public String getTitle()
{
return title;
}
//默认生成类型是void,将其修改为你的实体类名称,注意不要使用你的属性的修饰类型
public MetaVo setTitle(String title)
{
this.title = title;
//然后在加上这个return this;结束
return this;
}
public String getIcon()
{
return icon;
}
//默认生成类型是void,将其修改为你的实体类名称,注意不要使用你的属性的修饰类型
public MetaVo setIcon(String icon)
{
this.icon = icon;
//然后在加上这个return this;结束
return this;
}
public String getLink()
{
return link;
}
//默认生成类型是void,将其修改为你的实体类名称,注意不要使用你的属性的修饰类型
public MetaVo setLink(String link)
{
this.link = link;
//然后在加上这个return this;结束
return this;
}
@Override
public String toString() {
return "MetaVo{" +
"title='" + title + '\'' +
", icon='" + icon + '\'' +
", noCache=" + noCache +
", link='" + link + '\'' +
'}';
}
}
将set方法的返回类型修改为实体类,在其方法内加入return this;实体类编辑完成,
属性赋值的时候就可以进行链式编辑:
public static void main(String[] args) {
MetaVo metaVo = new MetaVo();
metaVo.setIcon("1")
.setTitle("2")
.setNoCache(true);
System.out.println(metaVo);
}
**当然现在大多数的实体类都采用lombok的@Data注解,**这样使代码更加简洁,示例如下:
@Data
//需要加上这个注解
@Accessors(chain = true)
public class Menu extends Model<Menu> {
}
另外,常用的StringBuffer的append()方法,是不是觉的很相似,源码如下: