当前位置: 首页 > news >正文

04-手机套餐:建造者模式

4.1关联背景故事

  去营业厅办理手机套餐,有以下两种套餐可以选择:

  1)20元包400条短信的套餐;

  2)30元包600条短信的套餐。

  并且两种套餐都必须开通彩铃业务。

4.2模式定义

  建造者模式(Builder Pattern),在一个软件系统中,可能会面临创建一些复杂对象的工作,如果我们使用单一的方法或单一的对象来创建会比较繁琐,当所创建的复杂对象发生变化时,整个系统就可能面临剧烈的变化。

  为了解决这个问题,我们可以将这个复杂对象的创建过程分解成若干个部分,各个子部分用一定的算法构成。但是,子部分可能会经常发生改变,如何能保证整体创建工作的稳定性呢?这就需要建造者模式的支持了。建造者模式把复杂对象的创建与表示分离,使得同样的构建过程可以创建不同的表示。

4.3故事中的模式分析

4.3.1角色分析

  例子中出现的事物对象有:

  1)客户张三

  2)营业厅操作员

  3)设置客户套餐的计算机

  4)手机套餐

  客户张三就是最终获得手机套餐的终端,营业厅操作员相当于一个指导者的身份,只有操作员才知道客户需要什么样的套餐,而计算机充当着一个建造者的角色,计算机通过操作设置客户的手机套餐,手机套餐就是最终的产品,生产出来给客户使用。

  例子中的各种角色列出如下:

  客户张三——终端需求

  营业厅操作员——指导者(通知指导建造者生产什么样的手机套餐)

  计算机——建造者(建造各种手机套餐)

  手机套餐——产品

4.3.2建造者模式的静态建模

  

  如图所示,在建造者工厂中将构建手机套餐对象细化分解成三个过程:构建话费、构建短信、构建彩铃。每一个过程实现的功能很专业化、单一化,三个功能又互不干扰,还有一个功能返回手机套餐实例,使构建和表示分离,功能模块之间的耦合度大大降低,模块内部具有很高的内聚度。

4.4模式实现

4.4.1创建产品——手机套餐

package com.demo.builder.model;

/**
 * Created by lsq on 2018/3/14.
 * 手机套餐类
 */
public class MobilePackage {

    //话费
    private float money;

    //短信
    private int shortInfo;

    //彩铃
    private String music;

    public float getMoney() {
        return money;
    }

    public void setMoney(float money) {
        this.money = money;
    }

    public int getShortInfo() {
        return shortInfo;
    }

    public void setShortInfo(int shortInfo) {
        this.shortInfo = shortInfo;
    }

    public String getMusic() {
        return music;
    }

    public void setMusic(String music) {
        this.music = music;
    }
}

4.4.2建立抽象建造者

1)建造者接口——IMobileBuilder

package com.demo.builder.itf;

import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/14.
 * 手机套餐建造者
 */
public interface IMobileBuilder {

    //建造手机套餐的话费
    public void buildMoney();

    //建造手机套餐的短信
    public void buildShortInfo();

    //建造手机套餐的彩铃
    public void buildMusic();

    //返回建造的手机套餐对象
    public MobilePackage getMobilePackage();

}

2)抽象建造者——AbstractBasePackage

package com.demo.builder.base;

import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/14.
 * 抽象建造者
 */
public abstract class AbstractBasePackage {

    //手机套餐实例变量
    protected MobilePackage mobilePackage;

    public AbstractBasePackage() {
        this.mobilePackage = new MobilePackage();
    }
}

4.4.3建立具体建造者

1)具体的建造者——MobileBuilderImpl1

package com.demo.builder.itf;

import com.demo.builder.base.AbstractBasePackage;
import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/14.
 * 套餐1
 */
public class MobileBuilderImpl1 extends AbstractBasePackage implements IMobileBuilder {

    //建造手机套餐的话费
    public void buildMoney() {
        this.mobilePackage.setMoney(20.0f);
    }

    //建造手机套餐的短信
    public void buildShortInfo() {
        this.mobilePackage.setShortInfo(400);
    }

    //建造手机套餐的彩铃
    public void buildMusic() {
        this.mobilePackage.setMusic("我们都一样");
    }

    //返回建造的手机套餐对象
    public MobilePackage getMobilePackage() {
        return this.mobilePackage;
    }
}

2)具体建造者——MobileBuilderImpl2

package com.demo.builder.itf;

import com.demo.builder.base.AbstractBasePackage;
import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/14.
 * 套餐2
 */
public class MobileBuilderImpl2 extends AbstractBasePackage implements IMobileBuilder {

    //建造手机套餐的话费
    public void buildMoney() {
        this.mobilePackage.setMoney(30.0f);
    }

    //建造手机套餐的短信
    public void buildShortInfo() {
        this.mobilePackage.setShortInfo(600);
    }

    //建造手机套餐的彩铃
    public void buildMusic() {
        this.mobilePackage.setMusic("我们不一样");
    }

    //返回建造的手机套餐对象
    public MobilePackage getMobilePackage() {
        return this.mobilePackage;
    }
}

4.4.4创建指导者

  指导者类含有一个方法,该方法以建造者实例对象作为参数,设置客户话费、短信和彩铃信息,然后返回手机套餐实例。

package com.demo.builder.director;

import com.demo.builder.itf.IMobileBuilder;
import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/14.
 * 手机套餐指导者
 */
public class MobileDirector {

    public MobilePackage createMobilePackage(IMobileBuilder mobileBuilder){
        if (mobileBuilder != null){
            //构建话费
            mobileBuilder.buildMoney();
            //构建短信
            mobileBuilder.buildShortInfo();
            //构建彩铃
            mobileBuilder.buildMusic();

            //返回手机套餐
            return mobileBuilder.getMobilePackage();
        }
        return null;
    }

}

4.4.5客户订购手机套餐

import com.demo.builder.director.MobileDirector;
import com.demo.builder.itf.MobileBuilderImpl1;
import com.demo.builder.itf.MobileBuilderImpl2;
import com.demo.builder.model.MobilePackage;

/**
 * Created by lsq on 2018/3/13.
 *
 */
public class MainApp {

    public static void main(String[] args) {

        //创建指导者
        MobileDirector mobileDirector = new MobileDirector();
        //套餐1
        MobileBuilderImpl1 mobileBuilderImpl1 = new MobileBuilderImpl1();
        //套餐2
        MobileBuilderImpl2 mobileBuilderImpl2 = new MobileBuilderImpl2();

        printMessage(mobileDirector.createMobilePackage(mobileBuilderImpl1));

        printMessage(mobileDirector.createMobilePackage(mobileBuilderImpl2));

    }

    /**
     * 打印输出套餐信息
     */
    public static void printMessage(MobilePackage mobilePackage){
        System.out.println("--话费:"+mobilePackage.getMoney()+"\t短信:"
                +mobilePackage.getShortInfo()+"条\t彩铃:"+mobilePackage.getMusic());
    }

}

执行结果:

实现的代码结构:

  从以上的代码不难看出,其实指导者只是一个中介服务而已,最终还是建造者设置实例对象,最后返回给终端客户,那为什么还要指导者角色呢?

  指导者确实是一个中间的服务,但是其所起的作用是不能小觑的,正是指导者的角色起到了对构建者构建产品过程的封装,有效的减少了客户端使用构建者构建产品的各个过程。假如一个复杂产品的构建需要十几个过程甚至更多,如果在客户端一步一步使用构建者来构建复杂对象,那么客户端的复杂程度可想而知,最重要的一点是,客户端需要的是最终产品,构建过程客户端是不需要关心的。所以,指导者角色的存在是有一定道理的。

4.6使用场合

  1)当生成的产品对象内部具有复杂的结构时;

  2)当复杂对象需要与表示分离时,可能需要创建不同的表示时;

  3)当需要向客户端隐藏产品内部结构的表现时。

  建造者模式的优点在于其构建和表示的分离,有效地将复杂对象处理过程分解,降低功能模块之间的耦合度,增强模块内部的内聚度,使得其在软件设计模式中具有极其重要的位置。建造者设计模式的结构如图4-6所示:

  

  其实,建造者模式可以简化处理,将指导者角色去掉。如图4-7所示:

  

 

  经过以上的内容,你可以这样简单地理解建造者模式:在建造者内部存在一个具体产品的对象实例,所有的构建功能都是针对这个对象实例进行的, 而这个对象实例就是我们最终想要的东西或者是该对象实例的其他表现形式。这就相当于,先在水缸中存满足够的水,等到想喝水的时候不用打开水龙头接水喝,直接从缸里舀水就行。当然,即使水缸中没有接满足够的水(构建对象的各个功能是彼此独立的),你也还是能喝到水的(构建和表示分离)。

 

扩展:建造者模式和抽象工厂模式的区别

1)建造者模式着重于分步骤构造一个复杂对象,而抽象工厂模式则着重于多个系列的产品对象即对象族的构造;

2)建造者模式是在最后一步返回具体产品,而抽象工厂模式则是立即返回具体产品。

 

转载于:https://www.cnblogs.com/danielleee/p/8568699.html

相关文章:

  • css总结1:position定位:absolute/relative/fixed
  • zzw原创_非root用户启动apache的问题解决(非root用户启动apache的1024以下端口)
  • SQL循环语句 详解
  • OpenCV问题集锦
  • 20154327 Exp1 PC平台逆向破解
  • ios 通知与通知传值2018.03.17
  • 20155307《网络对抗》PC平台逆向破解(二)
  • 273. Integer to English Words
  • DevOps是一种文化,不是角色!
  • 00004、python+selenium 的三种时间等待方式
  • SQL SERVER存储过程一
  • HTML中nbsp; ensp; emsp; thinsp;等6种空白空格的区别
  • P1280 尼克的任务
  • 动态代理和AOP
  • php 实现SFTP上传文件
  • 30秒的PHP代码片段(1)数组 - Array
  • Angular 4.x 动态创建组件
  • download使用浅析
  • Effective Java 笔记(一)
  • maya建模与骨骼动画快速实现人工鱼
  • React-flux杂记
  • vue的全局变量和全局拦截请求器
  • Vue全家桶实现一个Web App
  • 聊聊flink的TableFactory
  • 入手阿里云新服务器的部署NODE
  • 推荐一个React的管理后台框架
  • 追踪解析 FutureTask 源码
  • 自制字幕遮挡器
  • Hibernate主键生成策略及选择
  • linux 淘宝开源监控工具tsar
  • 浅谈sql中的in与not in,exists与not exists的区别
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #if 1...#endif
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (超简单)构建高可用网络应用:使用Nginx进行负载均衡与健康检查
  • (二)Linux——Linux常用指令
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (一)为什么要选择C++
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (最优化理论与方法)第二章最优化所需基础知识-第三节:重要凸集举例
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .bat文件调用java类的main方法
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .net 后台导出excel ,word
  • .Net 中的反射(动态创建类型实例) - Part.4(转自http://www.tracefact.net/CLR-and-Framework/Reflection-Part4.aspx)...
  • .net2005怎么读string形的xml,不是xml文件。
  • .Net8 Blazor 尝鲜
  • .NetCore项目nginx发布
  • .NET的数据绑定
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • [AX]AX2012 SSRS报表Drill through action