最近在学习设计模式,想要记录下来,今天就记录在android和Java中都使用得非常广泛的建造者模式(参照《Java与模式》一书)。
先看一下什么是建造模式:
- 建造者模式(Builder):将一个产品的内部表象(Internal Representation)与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
建造者模式涉及的四个角色:
-
抽象建造者(Builder)角色: 给出一个抽象接口,以规范产品对象的各个组成成分的构造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者(ConcreteBuilder)角色。具体建造者类必须实现这个接口所要求的两种方法:一种是建造方法;另一种是结果返还方法。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少零件,就有多少相应的建造方法
-
具体建造者(Concrete Builder)角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:实现抽象建造者Builder所声明的接口,给出一步一步地完成创建产品实例的操作;在建造过程完成后,提供产品的实例
-
导演者角色(Director):担任这个角色的类调用具体建造者角色以创建产品对象。应当指出的是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色
-
产品(Product)角色:产品(Product)便是建造中的复杂对象。一般来说,一个系统中会有多于一个的产品类,而且这些产品类并不一定有共同的接口,而完全可以是不相关联的
/**
* 产品类角色:这个类是与应用系统紧密相关的
* @author Administrator
*
*/
public class Product
{
}
/**
* 抽象建造者角色:通常与应用系统的商业逻辑无关,会给出抽象接口,以规范产品对象的各个组成成分的构造
* @author Administrator
*
*/
public abstract class Builder
{
/**
* 产品零件建造方法
*/
public abstract void buildePart1();
/**
* 产品零件建造方法
*/
public abstract void buildePart2();
/**
* 产品返还方法
* @return
*/
public abstract Product retrieveResult();
}
/**
* 具体建造者角色:与应用系统的商业逻辑紧密相关的,应当将产品实例化,并在各个建造方法中建造产品的各个零件,并通过方法retrieveResult()
* 返回最终产对象
*
* @author Administrator
*
*/
public class ConcreteBuilder extends Builder
{
private Product product = new Product();
@Override
public void buildePart1()
{
System.out.println("建造第一部分");
}
@Override
public void buildePart2()
{
System.out.println("建造第二部分");
}
@Override
public Product retrieveResult()
{
return product;
}
}
/**
* 导演者角色:与客户端打交道的角色,导演者角色将客户端创建产品的请求划分为对各个零件的建造请求,再将这些请求
* 委派给具体建造者角色
* @author Administrator
*
*/
public class Director
{
private Builder builder;
/**
* 产品构造方法,负责调用各个零件建造方法
*/
public void construct()
{
builder = new ConcreteBuilder();
builder.buildePart1();
builder.buildePart2();
}
}
/**
* 客户端,测试
*/
public class Client
{
public static void main(String[] args)
{
Director director = new Director();
Product product = director.construct();//此为我们最终要得到的产品
}
}
输出结果:
建造第一部分
建造第二部分
我觉得学习设计模式需要一定的时间跨度,我之所以把现在读到和想到的记录下来,是为了以后更好的翻阅。现在,来看一看它的变体,为的是更好的理解我们在日常Java和Android编程中所见的建造者模式。
省略导演者角色和抽象建造者角色
在具体建造者只有一个的情况下,如果抽象建造者角色已经被省略掉,那么还可以进一步省略掉导演着角色(看能不能画图),此时Builder角色自己就扮演了导演着和建造者的角色,有改变的类只有Builder类。此时的示意性代码就成了这样:public class Builder {
private Product product = new Product();
/**
* 产品零件建造方法
*/
public void buildPart1(){
}
/**
* 产品零件建造方法
*/
public void buildPart2(){
}
public Product retrieveResult(){
return product;
}
/**
* 产品构造方法,负责调用各个零件建造方法
*/
public void construct(){
buildPart1();
buildPart2();
}
}
public class Client{
public static void main(String[] args){
Builder builder = new Builder();
builder.construct();
Product product = builder.retrieveResult();
}
}
public class Builder {
private Product product = new Product();
/**
* 产品零件建造方法
*/
public void buildPart1(){
}
/**
* 产品零件建造方法
*/
public void buildPart2(){
}
public Product retrieveResult(){
return product;
}
/**
* 产品构造方法,负责调用各个零件建造方法
*/
public void construct(){
buildPart1();
buildPart2();
}
}
public class Client{
public static void main(String[] args){
Builder builder = new Builder();
builder.construct();
Product product = builder.retrieveResult();
}
}
StringBuilder sb = new StringBuilder();
String str = sb.append("hello").append("world").append("welcome").toString();
这里面就是省略了导演者和抽象建造者角色的建造者模式,作为写这些代码的地方就是客户端,而StringBuilder就是那个具体建造者,最终的String就是产品角色。
再来看AlertDialog:
new AlertDialog.Builder(this).setTitle("数据删除").setMessage("你确定删除数据吗?")
.setPositiveButton("确定", new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Toast.makeText(DialogActivity.this, "删除成功",
Toast.LENGTH_SHORT).show();
}
}).setNegativeButton("取消", new OnClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which)
{
Toast.makeText(DialogActivity.this, "取消删除",
Toast.LENGTH_SHORT).show();
}
})
/*
* .setNeutralButton("Remind me later", new OnClickListener() {
*
* @Override public void onClick(DialogInterface dialog, int
* which) { Toast.makeText(DialogActivity.this, "以后再说",
* Toast.LENGTH_SHORT).show(); } })
*/
.show();
这里,同样是省略了导演者和抽象建造者角色的建造者模式,编写这些代码的地方就是客户端,而AlertDialog就是产品,AlertDialog.Builder类就是具体建造者,它在show()中将产品返回(实际上类似于前面retrieveResult()方法个人认为是在show中调用的create(),不过对整体理解丝毫没有影响)。今天就记录到这里~(不足之处欢迎指出~)