您的位置:首页 > 其它

研磨设计模式(七)生成器模式

2016-12-20 18:06 417 查看

1. 概述

在生活上,我们经常需要一个指南,按照一定的步骤去完成一件事情,很多符合条件的人都可以按照指南上的步骤去完成这件事情,但是不用关心这些个人是如何完成这些步骤的。这类情况就有点像是设计模式中的生成器模式(Builder)

2. 生成器模式

定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

生成器模式结构图如下



其中:

Builder:生成器接口,定义创建一个Product对象所需的各个部件的操作。

ConcreteBuilder:具体的生成器实现,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。

Director: 指导者,也被称为导向者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象。

Product:产品,表示被生成器构建的复杂对象,包含多个部件。

下面用代码实现一下

(1)先看看生成器的接口定义,示例代码如下:

/**
* 生成器接口,定义创建一个产品对象所需的各个部件的操作
*/
public interface Builder {
/**
* 示意方法,构建某个部件
*/
public void buildPart();
}


(2)再看看具体的生成器实现,示例代码如下:

/**
* 具体的生成器实现对象
*/
public class ConcreteBuilder implements Builder {
/**
* 生成器最终构建的产品对象
*/
private Product resultProduct;
/**
* 获取生成器最终构建的产品对象
* @return 生成器最终构建的产品对象
*/
public Product getResult() {
return resultProduct;
}

public void buildPart() {
//构建某个部件的功能处理
}
}


(3)看看相应的产品对象的接口示意,示例代码如下:

/**
* 被构建的产品对象的接口
*/
public interface Product {
//定义产品的操作
}


(4)再来看看指导者的实现示意,示例代码如下:

/**
* 指导者,指导使用生成器的接口来构建产品的对象
*/
public class Director {
/**
* 持有当前需要使用的生成器对象
*/
private Builder builder;

/**
* 构造方法,传入生成器对象
* @param builder 生成器对象
*/
public Director(Builder builder) {
this.builder = builder;
}

/**
* 示意方法,指导生成器构建最终的产品对象
*/
public void construct() {
//通过使用生成器接口来构建最终的产品对象
builder.buildPart();
}
}


代码实现就到此结束了,下面用个具体实例的来加强理解。

3. 使用生成器模式

在前几年的手机里,诺基亚和三星占了很大的市场份额。大家应该还记得诺基亚的强大,手机一摔,直接分成3块,机身、电池和手机后盖,然后再把它们组装回去,又可以继续用了~~

现在,我就把手机当做(Product),诺基亚和三星手机便是手机的不同实现,而机身、电池和手机后盖就是手机的部件(Part),这些部件是制造商分别生产的。把这三个部件组装在一起,就可以使用该手机了。而组装步骤很简单:

将电池装上机身。

将手机后盖盖上。

现在就可以用代码来实现一下这个场景。

(1)先是手机的三个组成部件类,这些部件只有一个
brand
字段代表品牌,其它细节便在此略过了~

1、机身(Body)

/**
* 机身
*/
public class Body {
// 所属品牌
private String brand;
// ..其它细节

public Body(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
}


2、电池(Battery)

/**
* 电池
*/
public class Battery {
// 所属品牌
private String brand;
// ..其它细节

public Battery(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
}


3、手机后盖(BackCover)

/**
* 手机后盖
*/
public class BackCover {
// 所属品牌
private String brand;
//..其它细节

public BackCover(String brand) {
this.brand = brand;
}
public String getBrand() {
return brand;
}
}


(2)手机类(Phone),有三个字段分别对应上面的三个部件类,并提供各自的getter和setter方法

/**
* 手机
*/
public class Phone {

private Body body;//机身
private Battery battery;//电池
private BackCover backCover;//后盖

public void setBody(Body body) {
this.body = body;
}
public void setBattery(Battery battery) {
this.battery = battery;
}
public void setBackCover(BackCover backCover) {
this.backCover = backCover;
}
public Body getBody() {
return body;
}
public Battery getBattery() {
return battery;
}
public BackCover getBackCover() {
return backCover;
}
}


(3)生成器接口,定义了创建一个手机(Phone)对象所需的各个部件的操作

/**
* 生产器接口,定义创建手机所需的各个部件的操作
*/
public interface Builder {
/**
* 构建机身
*/
public void buildBody();
/**
* 构建电池
*/
public void buildBattery();
/**
* 构建后盖
*/
public void buildBackCover();
}


(4)具体生成器的实现,一个是诺基亚(Nokia)的实现,一个是三星(Samsung)的实现

1、诺基亚(Nokia)的生成器实现

/**
* 诺基亚实现生成器对象
*/
public class NokiaBuilder implements Builder{

private Phone phone = new Phone();
/**
* 具体构建诺基亚机身
*/
public void buildBody() {
Body body = new Body("Nokia");
phone.setBody(body);
}
/**
* 具体构建诺基亚电池
*/
public void buildBattery() {
Battery battery = new Battery("Nokia");
phone.setBattery(battery);
}
/**
* 具体构建诺基亚后盖
*/
public void buildBackCover() {
BackCover backCover = new BackCover("Nokia");
phone.setBackCover(backCover);
}

public Phone getPhone() {
return phone;
}
}


2、三星(Samsung)的生成器实现

/**
* 三星实现生成器对象
*/
public class SamsungBuilder implements Builder{

private Phone phone = new Phone();
/**
* 具体构建三星机身
*/
public void buildBody() {
Body body = new Body("Samsung");
phone.setBody(body);
}
/**
* 具体构建三星电池
*/
public void buildBattery() {
Battery battery = new Battery("Samsung");
phone.setBattery(battery);
}
/**
* 具体构建三星后盖
*/
public void buildBackCover() {
BackCover backCover = new BackCover("Samsung");
phone.setBackCover(backCover);
}

public Phone getPhone() {
return phone;
}
}


(5)指导者(Director),指导生成器进行具体的产品构建

public class Director {

/**
* 生成器对象,通过构造方法传进来
*/
private Builder builder;

public Director(Builder builder) {
this.builder = builder;
}

/**
* 指导生成器构建产品
*/
public void construct(){
//1.构建机身
builder.buildBody();
//2.构建电池
builder.buildBattery();
//3.构建后盖
builder.buildBackCover();
}
}


(6)客户端(Client)来测试一下

public class Client {

public static void main(String[] args) {
// 创建具体的生成器
NokiaBuilder builder = new NokiaBuilder();
// SamsungBuilder builder = new SamsungBuilder();
// 创建指导者,并将生成器传入
Director director = new Director(builder);
// 指导者指导生成器构建产品
director.construct();
// 经过以上步骤,此时生成器中的手机对象便构建完毕
Phone phone = builder.getPhone();
// 将手机各个组件的品牌输出,看看是否一致
System.out.println("机身:" + phone.getBody().getBrand());
System.out.println("电池:" + phone.getBattery().getBrand());
System.out.println("后盖:" + phone.getBackCover().getBrand());
}
}


最终输出结果

机身:Nokia
电池:Nokia
后盖:Nokia


那么到此,生成器模式的使用就结束了,你可以发现,如果不使用生成器模式的话,那么在组装手机的时候,在每个具体的实现里都要重复这几个步骤,而生成器模式可以很好的将这些步骤“外包”给别人(指导者),分工鲜明。

4. 思考生成器模式

我觉得生成器模式最重要的两个角色就是生成器(Builder)和指导者(Director)

生成器:生成器定义了一个产品所需的各个部件的构建操作,但是如果它还要负责各个部件组装成一个产品的话,那就有点累了,这样子就不能完全关心自己分内的事情一样。就像是一个老师,除了专门教书外,还要管理学生的生活问题,这样子实在是浪费人才。

指导者:指导者知道如何将各个产品的部件组合成一个产品,不管他所接待的生产器给他生成的部件是如何实现的,生成器可以放心地将让指导者去捣鼓它生成的部件。就像是邓爷爷说的“不管白猫黑猫,抓到老鼠就是好猫”,给我一只猫(注意必须是猫哟),不管是黑的白的还是黄的花的,我都会训练它去给你抓老鼠~

不过要注意了,指导者的构建过程必须的统一的、固定不变的,变化的部分还是放在生成器中吧~

以上一部分内容参考至《研磨设计模式》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息