设计模式(0)简单工厂模式

设计模式(1)单例模式(Singleton)

设计模式(2)工厂方法模式(Factory Method)

设计模式(3)抽象工厂模式(Abstract Factory)

源码地址

0 建造者模式简介

0.0 建造者模式定义

建造者模式是一种常见的创建型模式,也称生成器模式。建造者模式的一般书面化定义为:将一个复杂对象的构建与该对象的表示分离,使得同样的构建过程可以创建不同的表示

建造者模式主要用于构建复杂产品,并且该产品是可以步骤化或者模块化的,最终可以根据步骤或模块组装创建出一个复杂产品。

现实生活中我们每天都在使用的手机有不同品牌不同型号,千差万别,但他们都具有屏幕、电池、外壳、核心(CPU、GUPU、ROM、RAM等)共性模块,即他们的创建过程是一致的,变化的只是每个步骤/模块的详细实现细节。这种情景是使用创建者模式的最佳时机,最终产品构建过程是统一且固定的,我们将变化的部分交给建造者,只需要配置不同的建造者,就可以使同样的构建过程生产出完全不同的产品。

建造者模式的结构图如下

Director:指导者,主要用来使用Buider接口,以一个统一固定的过程生产最终的产品Product

Builder:建造者抽象接口,定义创建一个Product对象所需各个部件的操作。在该接口中一般要求包含创建部件的方法如buidPartA,buidPartB等,同时还要包含一个获取最终创建的复杂对象的方法getResult()。builder可以定义为一个抽象类或者接口

ConcreteBuilder:具体的建造者实现,继承自Builder接口,实现接口中定义的创建部件及返回产品的方法。在这里不同的创建者实现类,对同一部件或步骤进行不同的详细实现,来完成不同产品的创建。

Product:最终产品类,表示被建造者构建出来的复杂对象,其用于多个固定的部件或步骤。

0.1 建造者模式应用场景

我们以英雄祭坛里造英雄这一过程为例。在使用模式之前,我们最直接的代码应该像下面这样。

恶魔猎手创建类

/// <summary>
/// 恶魔猎手创建类
/// </summary>
public class DH
{
/// <summary>
/// 创建英雄
/// </summary>
/// <returns></returns>
public string BuilderHero()
{
string body = "黑夜给了我黑色眼睛,我却用它去寻找光明。"; // 创建身体
string weapon = "艾辛诺斯双刃。"; // 创建武器
string mount = "我有这双脚有这双腿。"; // 创建坐骑
return body + weapon + mount;
}
}

同样,月之女祭司创建类

/// <summary>
/// 月之女祭司创建类
/// </summary>
public class POM
{
/// <summary>
/// 创建英雄
/// </summary>
/// <returns></returns>
public string BuilderHero()
{
string body = "夜幕只为朱颜改,群星陨落无穷。"; // 创建身体
string weapon = "索利达尔·群星之怒。"; // 创建武器
string mount = "艾斯卡达尔。"; // 创建坐骑
return body + weapon + mount;
}
}

客户调用时只需要实例化不同的英雄创建类,来完成对应英雄的创建。

DH dh = new DH();
Console.WriteLine(dh.BuilderHero());
POM pom = new POM();
Console.WriteLine(pom.BuilderHero());
Console.ReadLine();

这样我们需要别的英雄时只需要再添加一个创建该英雄对应的类。

我们这里只是简单的通过一句话描述创建了英雄身体、武器、坐骑三个关键部位,而实际中一个复杂产品的构件过程是远远要复杂的多,比如我们常见的文件导出,一个文件有头、内容、尾部说明三类内容,导出txt格式跟导出xml格式的操作,每个部位的创建都要根据不同的格式进行处理。

同时我们发现这样一种情况,每个英雄创建类中创建英雄的方法其实都是同一种模式,处理步骤完全一样,唯一变化的部分就在于每个步骤的具体实现细节,我们自然会考虑

1、创建每个英雄都要用到同样的步骤,对与固定不变的部分,我们要提炼出来,形成统一且公用的处理过程

2、英雄不只这两个,还会有很多其他英雄需要创建,要求我们在处理过程不变的情况下,能实现创建不同英雄的需要

也就是说,我们的固定不变的处理过程应该和变化的具体实现分离,从而达到固定处理过程的复用,同时还能满足不同具体实现的需求,此时的需求已经和前面介绍过的建造者模式非常贴近了。

1 建造者模式详解

0、提炼具体产品类

将上面用字符串表示的英雄的三个特征使用一个英雄类表示

/// <summary>
/// 英雄类
/// </summary>
public class Hero
{
/// <summary>
/// 身体特征
/// </summary>
public string Body { get; set; } /// <summary>
/// 武器
/// </summary>
public string Weapon { get; set; } /// <summary>
/// 坐骑
/// </summary>
public string Mount { get; set; }
}

1、建造者接口

建造者接口包含创建各部位的方法定义,及获取最终产品方法的定义

/// <summary>
/// 建造者接口
/// </summary>
public interface IBuilder
{
/// <summary>
/// 创建身体特征
/// </summary>
/// <returns></returns>
void BuildBody(); /// <summary>
/// 创建武器
/// </summary>
/// <returns></returns>
void BuildWepon(); /// <summary>
/// 创建坐骑
/// </summary>
/// <returns></returns>
void BuildMount(); /// <summary>
/// 获取最终产品
/// </summary>
/// <returns></returns>
Hero GetResult();
}

2、建造者具体实现类

恶魔猎手建造者实现类

/// <summary>
/// 恶魔猎手建造者实现类
/// </summary>
public class DHBuilder : IBuilder
{
private Hero _hero = new Hero(); /// <summary>
/// 创建身体特征
/// </summary>
/// <returns></returns>
public void BuildBody()
{
_hero.Body = "黑夜给了我黑色眼睛,我却用它去寻找光明。";
} /// <summary>
/// 创建武器
/// </summary>
/// <returns></returns>
public void BuildWeapon()
{
_hero.Weapon= "艾辛诺斯双刃。";
} /// <summary>
/// 创建坐骑
/// </summary>
/// <returns></returns>
public void BuildMount()
{
_hero.Mount= "我有这双脚有这双腿。";
} public Hero GetResult()
{
return _hero;
}
}

月之女祭司建造者类实现

/// <summary>
/// 月之女祭司建造者类
/// </summary>
public class POMBuilder : IBuilder
{
private Hero _hero = new Hero(); /// <summary>
/// 创建身体特征
/// </summary>
/// <returns></returns>
public void BuildBody()
{
_hero.Body = "夜幕只为朱颜改,群星陨落无穷。";
} /// <summary>
/// 创建武器
/// </summary>
/// <returns></returns>
public void BuildWeapon()
{
_hero.Weapon = "索利达尔·群星之怒。";
} /// <summary>
/// 创建坐骑
/// </summary>
/// <returns></returns>
public void BuildMount()
{
_hero.Mount = "艾斯卡达尔。";
} /// <summary>
/// 创建最终产品
/// </summary>
/// <returns></returns>
public Hero GetResult()
{
return _hero;
} }

3 、指导者实现

/// <summary>
/// 指导者
/// </summary>
public class Director
{
/// <summary>
/// 指导方法
/// </summary>
public void Construct(IBuilder builder)
{
builder.BuildBody(); // 创建身体特征
builder.BuildWeapon(); // 创建武器
builder.BuildMount(); // 创建坐骑
}
}

4、客户端调用

Director director = new Director();

DHBuilder buider1 = new DHBuilder();
director.Construct(buider1);
Hero dh = buider1.GetResult(); DHBuilder buider2 = new DHBuilder();
director.Construct(buider2);
Hero pom = buider1.GetResult();

2 总结

建造者模式具有一下优点

1、松散耦合

建造者模式把产品的构建过程独立出来,实现产品构建和产品表现的分离,从而使得构建算法可以复用,同时具体产品表现也可以灵活的扩展和切换。

2、可以很容易改变产品内部表示

在建造者模式中,Builder只提供接口给Director使用,具体的部件创建和装配方式有具体的创建者实现类实现,Director不关注具体实现细节,这样一来,如果像改变产品内部的表示,只需要修改具体建造者实现类即可。

3、更好的复用性

固定建造过程可以复用

设计模式(4)建造者模式/生成器模式(Builder)的更多相关文章

  1. 跟着实例学习设计模式(6)-生成器模式builder(创建型)

    生成器模式是创建型设计模式. 设计意图:将一个复杂的类表示与其构造相分离,使得同样的构建过程可以得出不同的表示. 实例类图: IVehicleBuilder:抽象建造者.为创建一个Vehicle对象并 ...

  2. Java设计模式之建造者模式(生成器模式)

    建造者模式: 也叫生成器模式.用来隐藏复合对象的创建过程,他把复合对象的创建过程加以抽象,通过子类继承和重载的方式,动态地创建具有复合属性的对象. 总结一句就是封装一个对象的构造过程,并允许按步骤构造 ...

  3. 设计模式C#实现(七)——生成器模式

    生成器模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. UML类图: 构成: 1.Builder(接口/抽象类)定义了创建一个产品Product的各个部件的方法,返回创 ...

  4. 设计模式 | 建造者模式/生成器模式(builder)

    定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 结构:(书中图,侵删) 一个产品类 一个指定产品各个部件的抽象创建接口 若干个实现了各个部件的具体实现的创建类 一个 ...

  5. 设计模式——建造者模式/生成器模式(C++实现)

    #include <iostream> #include <string> using namespace std; class STProduct { public: voi ...

  6. 1.6建造者模式(生成器模式) Builder

    1.概念:将一个复杂对象的构建和他的表示分离,使得同样的构件可以创建不同的表示. 2.实例:肯德基和中餐,肯德基抽象了整个做菜的复杂过程(相同的构建),然后在不同的店铺进行实现(不同的表示).中餐往往 ...

  7. 【设计模式】- 生成器模式(Builder)

    生成器模式 建造者模式.Builder 生成器模式 也叫建造者模式,可以理解成可以分步骤创建一个复杂的对象.在该模式中允许你使用相同的创建代码生成不同类型和形式的对象. 生成器的结构模式 生成器(Bu ...

  8. 设计模式十: 生成器模式(Builder Pattern)

    简介 生成器模式属于创建型模式的一种, 又叫建造者模式. 生成器模式涉及4个关键角色:产品(Product),抽象生成器(builder),具体生成器(ConcreteBuilder),指挥者(Dir ...

  9. C#设计模式——生成器模式(Builder Pattern)

    一.概述在软件系统中,有时候面临着复杂的对象创建,该对象由一定算法构成的子对象组成,由于需求变化,这些子对象会经常变换,但组合在一起的算法却是稳定的.生成器模式可以处理这类对象的构建,它提供了一种封装 ...

随机推荐

  1. raft如何实现leadership transfer

    leadership transfer可以把raft group中的leader身份转给其中一个follower.这个功能可以用来做负载均衡,比如可以把leader放在性能更好的机器或者离客户端更近的 ...

  2. Vue2.0 生产环境部署

    简要:继上次搭建vue环境后,开始着手vue的学习;为此向大家分享从开发环境部署到生产环境(线上)中遇到的问题和解决办法,希望能够跟各位VUE大神学习探索,如果有不对或者好的建议告知下:*~*! 一. ...

  3. 怎么调试nodejs restful API 以及API的Authorization

    最近Nodejs,python越来越火了,同时也越来越多的人在用node写服务,可是怎么去调试服务呢?以及当你一个服务发布出去,怎么保证其安全性呢? 环境:linux unbuntu 语言:nodej ...

  4. QuartusII 13.0 PLL IP Core调用及仿真

    有一个多月没用用Quartus II了,都快忘了IP 是怎么用调用的了,还好有之前做的笔记,现在整理出来,终于体会到做笔记的好处. 一.  QuartusII的pll的调用 打开软件界面 Tool—— ...

  5. Python面向对象编程(二)

    1.继承与派生 上文我们已经说过,Python中一切皆对象.我们从对象中抽取了共同特征和技能,得到了类的概念.类与类之间也有共同特征,我们可以从有共同特征和技能的类中提取共同的技能和特征,叫做父类. ...

  6. 【.net 深呼吸】自己动手来写应用程序设置类

    在开始装逼之前,老周先说明一件事.有人说老周写的东西太简单了,能不能写点复杂点.这问题就来了,要写什么东西才叫“复杂”?最重要的是,写得太复杂了,一方面很多朋友看不懂,另一方面,连老周自己也不知道怎么 ...

  7. Jenkins2 实现持续交付初次演练(MultiJob,Pipeline,Blue Ocean)

    背景 项目需要用到自动部署,但可获取外网的节点机器只有一台,那只能同过主节点机器进行构建完成然后分发至对应服务器进行启动更新. 目前已尝试过三种方式: 1.Pipeline-Trigger param ...

  8. (转)Linux命令unzip

    场景:解压war包时候用到该命令,感觉很方便. 1 基本用法 unzip [选项] 压缩文件名.zip 1.2 完整语法 unzip [-cflptuvz] [-agCjLMnoqsVX] [-P & ...

  9. Objective-C plist文件与KVC 的使用

    plist文件是以类似xml形式构造数据,下面我们直接在xcode中创建完成一个plist文件, File-New-File-属性列表 我们可以选择存储类型.这里我构造一组数据,数据中的每个元素都是一 ...

  10. 如何查看appache的端口是否被占用

    win + R 快捷键输入 cmd 打开命令行. 输入 netstat -ano 查看端口使用情况 Ctrl + Shift + Esc 打开 windows 任务管理器,依次单击 [查看][ 选择列 ...