设计模式-建造者模式
2016-02-21 16:26
411 查看
本文是对 设计模式-建造者模式 的介绍,主要从以下几个方面阐述:
模式介绍
两种分类
应用场景
实际应用示例
优缺点分析
示例代码已在 Github,请参考: Github
UML图:
(2) ConcreteBuilder:具体建造者角色,继承自抽象建造者,实现复杂对象各部件的构造和装配,并返回该对象。
(3) Director:指挥者角色,客户端通常只与该角色交互,通过construct()方法方法得到复杂对象。该方法主要有两个作用:一、依赖建造者的buildPartX() 方法安排组成部分的建造次序;二、通过getResult()方法得到复杂对象。
(4) Product:产品角色(复杂对象),通常定义为一个POJO,针对其中的每个成员对象都有一组公有的get()和set()方法。
对建造者(工人)的规范:
实现了 Builder 接口的工人:
设计师:
测试用例:
测试用例:
可以看出,AlertDialog 直接命令 Builder ,并没有涉及到 Designer,所以它是无序的。
一个对象可以配置多个不同的零件,产生不同的效果
一个对象,参数方法极多,调用顺序不同则效果不同
ImageLoader.ImageOptions:
DraweeController:
DraweeHierarchyBuilder:
Builder 工厂是可插拔的、可扩展的。通过修改 Builder ,甚至设置多个 Builder 满足较为复杂的需求
设计模式之建造者模式(Builder)
设计模式总结篇系列:建造者模式(Builder)
一种改进的建造者设计模式 欧阳宏基
模式介绍
两种分类
应用场景
实际应用示例
优缺点分析
示例代码已在 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)
一种改进的建造者设计模式 欧阳宏基
相关文章推荐
- 学术组织与机构
- HDU1062:Text Reverse
- http://blog.csdn.net/antjumper/article/details/39479187
- WinCE 下实现 ping 功能
- Linux 之 awk 命令
- MySQL连接查询
- 飞思卡尔9S12X系列双核中的协处理器XGATE使用方法
- 转:Spring 资源访问剖析和策略模式应用
- 支付宝集成
- ZOJ-3203-Light Bulb【6th浙江省赛】【数学公式】【三分】
- 面向对象5
- POJ 3267 The Cow Lexicon(DP单词匹配)
- 迟来的2015总结
- 构建单页Web应用
- 简单的音乐播放器
- WP8 电话本编程
- 51 nod 1181 质数中的质数(质数筛法)
- Android问题集(八)——
- PowerDNS简单教程(1):安装篇
- 面向对象之多态