您的位置:首页 > 其它

设计模式-建造者模式

2016-02-21 16:26 411 查看
本文是对 设计模式-建造者模式 的介绍,主要从以下几个方面阐述:

模式介绍

两种分类

应用场景

实际应用示例

优缺点分析

示例代码已在 Github,请参考: Github

模式介绍

建造者模式(BuilderPattern)又称为生成器模式,该模式主要用于将一个复杂对象的构建与它的表示分离,向用户屏蔽复杂对象组成部分的创建细节,使得同样的构建过程可以创建不同的表示。建造者模式通常包含如下4个角色

UML图:



角色介绍

(1) Builder:抽象建造者角色,主要为创建产品对象的各组成部分指定抽象接口,一般包含两类方法,其中buildPartX()用于创建复杂对象的各部分,此种方法的数量取决于复杂对象组成部分的多少;getResult()用于返回复杂对象。

(2) ConcreteBuilder:具体建造者角色,继承自抽象建造者,实现复杂对象各部件的构造和装配,并返回该对象。

(3) Director:指挥者角色,客户端通常只与该角色交互,通过construct()方法方法得到复杂对象。该方法主要有两个作用:一、依赖建造者的buildPartX() 方法安排组成部分的建造次序;二、通过getResult()方法得到复杂对象。

(4) Product:产品角色(复杂对象),通常定义为一个POJO,针对其中的每个成员对象都有一组公有的get()和set()方法。

建造者模式的分类

根据产品创建过程中零件的构造是否具有一致的先后顺序,可以将其分为“有设计者” 和 “无设计者”,两种形式。

有设计者

在现实生活中,建造一个房子,但我们不知道怎么造,就要请负责总体设计的设计师和负责具体施工的工人,设计师只设计图纸、命令工人干活,不参与施工。工人负责具体细节(窗户、地板的构建)。最后,我们要从工人手中接过建造好的房子。

对建造者(工人)的规范:

package cn.house;

public interface Builder {

/**
* 建造窗户
*/
public void mkWindow();

/**
* 建造房屋
*/
public void mkFloor();

/**
* 获取房间
*/
public Room getRoom();
}


实现了 Builder 接口的工人:

package cn.house;

public class RoomBuilder implements Builder{
private Room room = new Room();

/** 具体创建窗户 */
public void mkWindow() {

Window window = new Window();
room.setWindow(window);
}

/** 具体创建地板 */
public void mkFloor() {

Floor floor = new Floor();
room.setFloor(floor);
}

/** 交付以创建好的房子 */
public Room getRoom() {
return room;
}

}


设计师:

package cn.house;

public class Designer {

/**
* 命令 Builder
* @param builder
*/
public void command(Builder builder){
// 建造房屋
builder.mkWindow();

// 建造地板
builder.mkFloor();
}
}


测试用例:

public static void main(String[] args) {

Builder builder = new RoomBuilder();
Designer design = new Designer();
design.command(builder);

Room room = builder.getRoom();
Window window = room.getWindow();
Floor floor = room.getFloor();

System.out.println(window);
System.out.println(floor);
}


无设计者

Android 中的 AlertDialog 就属于无设计者的形式,下面是 AlertDialog 的简单模拟:

package cn;

public class AlertDialog {
private String title;
private String message;
private int buttonCount;

private AlertDialog() {
// empty
}

/** 获取标题 */
public String getTitle() {
return title;
}

/** 获取信息 */
public String getMessage() {
return message;
}

/** 获取按钮数 */
public int getButtonCount() {
return buttonCount;
}

/** 显示 */
public void show(){
System.out.println("show");
}

/** 建造者 */
public static class Builder{
private AlertDialog entity = new AlertDialog();

public Builder(boolean isContext){
if (!isContext){
throw new RuntimeException("必须有上下文");
}
}

/** 设置标题 */
public Builder setTitle(String title) {
entity.title = title;
return this;
}

/** 设置内容 */
public Builder setMessage(String message) {
entity.message = message;
return this;
}

/** 设置按钮数 */
public Builder setButtonCount(int buttonCount) {
entity.buttonCount = buttonCount;
return this;
}

/** 交付结果 */
public AlertDialog build(){
return entity;
}
}

}


测试用例:

public static void main(String[] args) {
new AlertDialog.Builder(true)
.setTitle("Title")
.setMessage("Message")
.setButtonCount(2)
.build()
.show();
}


可以看出,AlertDialog 直接命令 Builder ,并没有涉及到 Designer,所以它是无序的。

建造者模式的应用场景

相同的方法,不同的执行顺序,产生不同的执行效果

一个对象可以配置多个不同的零件,产生不同的效果

一个对象,参数方法极多,调用顺序不同则效果不同

Android 开源项目中的应用

由于建造者模式本身的优点,极大简化了对象的创建,一般被用于生成某些配置对象。可以看到下面的代码是多么的简洁清晰,一目了然。

ImageLoader

ImageLoader.ImageLoaderConfiguration:

public static void initImageLoader(Context context) {
// // 获取到缓存的目录地址
File cacheDir = StorageUtils.getOwnCacheDirectory(context,"Cache");

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context)
// max width, max height,即保存的每个缓存文件的最大长宽
.memoryCacheExtraOptions(480, 800)
// 设置缓存的详细信息,最好不要设置这个
// Can slow ImageLoader, use it carefully (Better don't use it)
// 线程池内加载的数量
.threadPoolSize(3)
// 线程优先级
.threadPriority(Thread.NORM_PRIORITY - 2)
//硬盘缓存50MB
.diskCacheSize(50 * 1024 * 1024)
//将保存的时候的URI名称用MD5
.diskCacheFileNameGenerator(new Md5FileNameGenerator())
// 加密
.diskCacheFileNameGenerator(new HashCodeFileNameGenerator())
//将保存的时候的URI名称用HASHCODE加密
.tasksProcessingOrder(QueueProcessingType.LIFO)
//缓存的File数量
.diskCacheFileCount(100)
// 自定义缓存路径
.diskCache(new UnlimitedDiscCache(cacheDir))
.writeDebugLogs()
.build();

// 全局初始化此配置
ImageLoader.getInstance().init(config);
}


ImageLoader.ImageOptions:

public static DisplayImageOptions getListOptions() {
DisplayImageOptions options = new DisplayImageOptions.Builder()
// 设置图片在下载期间显示的图片
.showImageOnLoading(R.drawable.ic_stub)
// 设置图片Uri为空或是错误的时候显示的图片
.showImageForEmptyUri(R.drawable.ic_stub)
// 设置图片加载/解码过程中错误时候显示的图片
.showImageOnFail(R.drawable.ic_error)
// 设置下载的图片是否缓存在内存中
.cacheInMemory(false)
// 设置下载的图片是否缓存在SD卡中
.cacheOnDisc(true)
// 保留Exif信息
.considerExifParams(true)
// 设置图片以如何的编码方式显示
.imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
// 设置图片的解码类型
.bitmapConfig(Bitmap.Config.RGB_565)
// .decodingOptions(android.graphics.BitmapFactory.Options
// decodingOptions)//设置图片的解码配置
.considerExifParams(true)
// 设置图片下载前的延迟
.delayBeforeLoading(100)// int
// delayInMillis为你设置的延迟时间
// 设置图片加入缓存前,对bitmap进行设置
// .preProcessor(BitmapProcessor preProcessor)
.resetViewBeforeLoading(true)// 设置图片在下载前是否重置,复位
// .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少
.displayer(new FadeInBitmapDisplayer(100))// 淡入
.build();
return options;
}


Fresco

恰好最近学习了 Fresco,贴上 Fresco 最典型的 DraweeController 和 DraweeHierarchyBuilder:

DraweeController:

DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(uri)
.setTapToRetryEnabled(true)
.setOldController()
.setControllerListener(listener)
.build();

mSimpleDraweeView.setController(controller);


DraweeHierarchyBuilder:

GenericDraweeHierarchyBuilder builder =
new GenericDraweeHierarchyBuilder(getResources());

GenericDraweeHierarchy hierarchy = builder
.setFadeDuration(300)
.setPlaceholderImage(new MyCustomDrawable())
.setBackgrounds(backgroundList)
.setOverlays(overlaysList)
.build();
mSimpleDraweeView.setHierarchy(hierarchy);


优缺点分析

评价一个模式应该考虑它的优点和缺点两个方面,该模式优缺点如下

优点:

屏蔽了组件的内部细节,将组件本身和创建过程进行解耦分离,同一个 Builder 设置不同的参数,即可创建适应不同需求的组件

Builder 工厂是可插拔的、可扩展的。通过修改 Builder ,甚至设置多个 Builder 满足较为复杂的需求

缺点:

由建造者设计模式生产出的组件差异不大,所以针对特别灵活的生产过程,该模式就不再适用了

参考

Java之建造者模式(Builder-Pattern)

设计模式之建造者模式(Builder)

设计模式总结篇系列:建造者模式(Builder)

一种改进的建造者设计模式 欧阳宏基
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: