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

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. 将电池装上机身。
  2. 将手机后盖盖上。

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

(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)

  • 生成器:生成器定义了一个产品所需的各个部件的构建操作,但是如果它还要负责各个部件组装成一个产品的话,那就有点累了,这样子就不能完全关心自己分内的事情一样。就像是一个老师,除了专门教书外,还要管理学生的生活问题,这样子实在是浪费人才。
  • 指导者:指导者知道如何将各个产品的部件组合成一个产品,不管他所接待的生产器给他生成的部件是如何实现的,生成器可以放心地将让指导者去捣鼓它生成的部件。就像是邓爷爷说的“不管白猫黑猫,抓到老鼠就是好猫”,给我一只猫(注意必须是猫哟),不管是黑的白的还是黄的花的,我都会训练它去给你抓老鼠~

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

以上一部分内容参考至《研磨设计模式》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内容简介 · · · · · · 《研磨设计模式》完整覆盖GoF讲述的23个设计模式并加以细细研磨。初级内容从基本讲起,包括每个模式的定义、功能、思路、结构、基本实现、运行调用顺序、基本应用示例等,让读者能系统、完整、准确地掌握每个模式,培养正确的“设计观”;中高级内容则深入探讨如何理解这些模式,包括模式中蕴涵什么样的设计思想,模式的本质是什么,模式如何结合实际应用,模式的优缺点以及与其他模式的关系等,以期让读者尽量去理解和掌握每个设计模式的精髓所在。 《研磨设计模式》在内容上深入、技术上实用、和实际开发结合程度很高,书中大部分的示例程序都是从实际项目中简化而来,因此很多例子都可以直接拿到实际项目中使用。如果你想要深入透彻地理解和掌握设计模式,并期望能真正把设计模式应用到项目中去,那么这是你不可错过的一本好书。 《研磨设计模式》难度为初级到中级,适合与所有开发人员、设计人员或者即将成为开发人员的朋友。也可以作为高效学生深入学习设计模式的参考读物! 作者简介 · · · · · · 陈臣:十年Java/JavaEE开发经验,高级系统架构师,功力深厚,技术精湛,精通Java/JavaEE相关技术和多种开源框架,尤其擅长系统分析和架构设计。从事过专业的中间件研发,包括基于组件的Web页面框架、基于WFMC的工作流中间件、类似于Hibernate的ORM框架等等;参与或主持了多个中大型的企业级应用项目,拥有多年项目经理、技术部经理的管理经验。个人博客:http://www.javass.cn/javapeixunxxyd/index.html 王斌:从事Java/JavaEE开发五年,系统架构师,精通Ejb、Struts、Spring、Hibernate、iBatis等框架技术,擅长设计模式和Eclipse插件开发。作为架构小组骨干,参与了国旅电子商务平台、南王酒庄等多个项目的开发,开发并维护有constance4j、myxstream、SimpleMapping等多个公司内部开源框架,深得多个项目组好评。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值