设计模式 之美 -- 建造者模式
文章目录
- 1. 解决问题
- 2. 应用场景
- 3. 实现
- C语言实现
- C++实现
- 4. 缺点
1. 解决问题
描述如下场景:
- 类的数据成员很多(8个以上),当我们进行初始化的时候放在初始化列表中,影响类的可读性,同时校验初始化参数列表是否有效的逻辑也无处放置
- 假如初始化列表中的参数有一定的依赖关系,比如数据成员max 一定比 数据成员min 小才行,这样的依赖关系设置逻辑无处安放(需要在类实例化的时候就要完成依赖关系的创建)
- 类的对象是不可变的,也就是对象在创建好之后就不能再修改其内部的属性值。此时,我们不能对外暴露类的set成员函数。
针对以上三种关于 类实例化过程中遇到 的问题,我们可以使用建造者模式 解决。
2. 应用场景
- 一种类的设计较为复杂,需要通过设置不同的可选错参数,定制化地创建不同的对象
建造者模式和工厂模式的区别:
工厂模式:创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象
建造者模式:创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象
举例:
顾客走进餐馆点餐,我们使用工厂模式 根据用户的不同选择,制作不同的食物:汉堡,沙拉,披萨等。
对于披萨来说,用户可以有不同的配料选择:奶酪,西红柿,起司。此时我们通过建造者模式根据用户选择的不同配料制作披萨。
3. 实现
C语言实现
实现功能:
建造者模式实现简单的电脑组装,通过配置不同的config来组装出不同用户要求的电脑(稳定性高、性能高)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct PERSONAL_COMPUTER {char cpu[20];char memory[20];char harddisk[20];
}Personal_Computer;void assemble_intel_cpu(Personal_Computer* personal_computer)
{strncpy(personal_computer->cpu, "inter",sizeof("inter"));return;
}
void assemble_amd_cpu(Personal_Computer* personal_computer)
{strncpy(personal_computer->cpu, "amd", sizeof("amd"));return;
}
void assemble_samsung_memory(Personal_Computer* personal_computer)
{strncpy(personal_computer->memory,"samsung", sizeof("samsung"));return;
}
void assemble_kingston_memory(Personal_Computer* personal_computer)
{strncpy(personal_computer->memory, "kingston", sizeof("kingston"));return;
}
void assemble_hitachi_harddisk(Personal_Computer* personal_computer)
{strncpy(personal_computer->harddisk, "hitachi", sizeof("hitachi"));return;
}
void assemble_digital_harddisk(Personal_Computer* personal_computer)
{strncpy(personal_computer->harddisk, "digital", sizeof("digital"));return;
}struct PERSONAL_COMPUTER* builder_fast_config()
{struct PERSONAL_COMPUTER *Personal_Computer = NULL;Personal_Computer = (struct PERSONAL_COMPUTER*)malloc(sizeof(struct PERSONAL_COMPUTER));if (Personal_Computer == NULL) {return NULL;}assemble_intel_cpu(Personal_Computer);assemble_hitachi_harddisk(Personal_Computer);assemble_kingston_memory(Personal_Computer);return Personal_Computer;
}struct PERSONAL_COMPUTER* builder_safty_config()
{struct PERSONAL_COMPUTER* personal_computer = NULL;personal_computer = (struct PERSONAL_COMPUTER*)malloc(sizeof(struct PERSONAL_COMPUTER));if (personal_computer == NULL) {return NULL;}assemble_amd_cpu(personal_computer);assemble_digital_harddisk(personal_computer);assemble_samsung_memory(personal_computer);return personal_computer;
}int main()
{struct PERSONAL_COMPUTER* my_personal_computer = NULL;printf("safy style is :\n");my_personal_computer = builder_safty_config();printf("cpu: %s\n", my_personal_computer->cpu);printf("memory: %s\n", my_personal_computer->memory);printf("harddisk: %s\n", my_personal_computer->harddisk);printf("fast style is :\n");my_personal_computer = builder_fast_config();printf("cpu: %s\n", my_personal_computer->cpu);printf("memory: %s\n", my_personal_computer->memory);printf("harddisk: %s\n", my_personal_computer->harddisk);if (my_personal_computer != NULL) {free(my_personal_computer);}return 0;
}
输出如下:
safy style is :
cpu: amd
memory: samsung
harddisk: digital
fast style is :
cpu: inter
memory: kingston
harddisk: hitachi
C++实现
实现功能:
建造者负责根据product 类的初始化成员列表,构造不同需求的product对象,同时满足product类的成员有效性的校验。
#include <iostream>
#include <string>using namespace std;class Product{
private:string name;int max;int min;int total;/*构造函数声明为private,可以保证该类实例化无法再外部进行,只能由类内部自己进行*/Product(Builder builder) { (*this).name = builder.name;(*this).max = builder.max;(*this).min = builder.min;(*this).total = builder.total;}public:string getName() {return (*this).name;}int getMax() {return (*this).max;}int getMin() {return (*this).min;}int getTotal() {return (*this).total;}/*builder类设计成了Product的内部类,这里也可以设计Builer类为独立的非内部类*/static class Builder {private:const static int DEFAULT_MAX = 8;const static int DEFAULT_TOTAL = 8;const static int DEFAULT_MIN = 0;string name;int max = DEFAULT_MAX;int total = DEFAULT_TOTAL;int min = DEFAULT_MIN;public:/*这里进行Product类初始化成员的校验逻辑,包括必填校验项、依赖关系校验、约束条件等*/Product build(){if(name==""){throw "name is null!";}if(max > total) {throw "max bigger than total!"}if(max < min) {throw "max less than min!"}return new Product((*this));}/*设置名字*/Builder setName(string name) {if(name == "") {throw "name is null, illegal!";}(*this).name = name;return (*this);}/*设置最大值*/Builder setMax(int max) {if(max < 0) {throw "max is less than zero, illegal!";}(*this).max = max;return (*this);} /*设置总值*/Builder setTotal(int name) {if(total <= 0) {throw "total is less than zero, illegal!";}(*this).total = total;return (*this);}/*设置最小值*/Builder setMin(int min) {if(min < 0) {throw "min is less than zero, illegal!";}(*this).min = min;return (*this);}};
};int main(){Product product = new Product.Builder().setName("productA").setMax(16).setTotal(2).setMin(0).build();cout << "After product construct:"<< "name:" << product.getName() << endl<< "total:" << product.getTotal() << endl<< "max:" << product.getMax() << endl<< "min:" << product.getMin() << endl;return 0;
}
4. 缺点
工厂模式:创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象
建造者模式:创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。
综上,建造者模式仅仅是为了适配不同需求的对象,并不负责之后对象的处理;工厂模式则主要是针对接口开发,通过创建拥有相关性的不同对象来进行不同的操作。
相关文章:

dateformat java 并发_java.text.DateFormat 多线程并发问题
在日常开发中,java.text.DateFormat 应该算是使用频率比较高的一个工具类,经常会使用它 将 Date 对象转换成字符串日期,或者将字符串日期转化成 Date 对象。先来看一段眼熟的代码:类 DateUtils 的方法 formatForDay() 在多线程的情…

每天一个摆脱if-else工程师的技巧——优雅的参数校验
在日常的开发工作中,为了程序的健壮性,大部分方法都需要进行入参数据校验。最直接的当然是在相应方法内对数据进行手动校验,但是这样代码里就会有很多冗余繁琐的if-else。throw new IllegalArgumentException("用户姓名不能为空");throw new IllegalArgumentException("性别不能为空");throw new IllegalArgumentException("性别错误");

我下载的最新的linux ADT+eclipse中没有NDK
问题描述我下载的是 adt-bundle-linux-x86_64-20140702.zip 这个版本。我已经安装了CDT了,但是还是没有NDK可以设置,而且在project右键android tools下 没有Add Native Support这个选项求指教,谢谢! 解决方案1你的Eclipse插件好…

Android中去掉标题的方法总结
方法一:也一般入门的时候经常使用的一种方法在setContentView()方法的前面插入代码: requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏 package com.example.helloword;import android.os.Bundle; import android.app.Activity; import and…

ImportError: No localization support for language ‘eng’ in python
ImportError: No localization support for language ‘eng’ in python 遇到這一個問題,是因為有缺少檔案,我是因為使用 pyinstaller 去包裝執行檔,所以需要手動加入這一個設定值進 .spec 檔案裡: hiddenimports[mysql,mysql.con…

C++ 智能指针(unique_ptr / shared_ptr)代码实现
文章目录unique_ptr 智能指针的实现shared_ptr 智能指针的实现指针类型转换unique_ptr 智能指针的实现 一个对象只能被单个unique_ptr 所拥有。 #include <iostream>using namespace std;/*增加模板类型,保证智能指针的类型是由传入的类型决定的*/ template…

winform实现截图
这个截图模仿QQ截图,左键单击开始截图,鼠标移动出现方框确定截图尺寸,放开时为最终尺寸,双击鼠标弹出保存对话框进行保存。 还有一点就是,如果截图尺寸方框已经确定,移动鼠标到所选区域内时,鼠标…

java interface list_你了解注解内的@interface List么
Annotation, Multi-valued annotation, nested annotation, 多值注解, 嵌套注解今天在研究Spring MVC的Validation机制时(这里 | 还有这里),简单看了下一些注解的源码,比如Min,发现以前从来没注意到的注解写法。看来基础知识有疏漏啊.../*** …

Struts 2的输入校验(一)
9 Struts 2的输入校验输入校验有两种:客户端和服务器端校验。客户端校验一般是通过JavaScript来完成,这种校验可减轻服务器压力。服务器校验主要通过服务器端编程的方式来完成。(1) 客户端校验客户端校验一般是通过JavaScript来完成,这种校验…

通过document.domain实现跨域访问
通过document.domain实现跨域访问:https://blog.csdn.net/nlznlz/article/details/79506655 前端跨域方法之document.domain和location.hash:https://blog.csdn.net/WEB_YH/article/details/79364565 转载于:https://www.cnblogs.com/bydzhangxiaowei/p/…

设计模式 之美 -- 原型模式
文章目录1. 解决问题2. 应用场景3. 实现方式C实现C语言实现4. 缺点5. 和其他三种创建模式的对比(单例,工厂,建造者)1. 解决问题 如果对象的创建成本较大,而同一个类的不同对象之间的差别不大(大部分字段相…

Objective-C语法简记
开始学习iPhone开发了,虽然现在已经有了Swift,但我还是老老实实地学习Objective-C,鄙人入门的程序语言是C,后来学习了C#和Java,现在来学Objective-C,这篇只是一些很简略的笔记,不算是语法书。 代…

java编写最大公约数_Java编写最大公约数和最小公倍数
package javaapplication24;class NegativeIntegerException extends Exception{String message;public NegativeIntegerException(){message"方法的参数值不是正整数";}public String toString(){return message;}}class MaxCommonDivisor{public int getMaxCommonD…
肤色检测算法 - 基于不同颜色空间简单区域划分的皮肤检测算法
由于能力有限,算法层面的东西自己去创新的很少,很多都是从现有的论文中学习,然后实践的。 本文涉及的很多算法,在网络上也有不少同类型的文章,但是肯定的一点就是,很多都是不配代码的,或者所附带…

【算法学习】堆排序建立最大堆
本文代码均转自: 作者:早就戒了 来源:CSDN 原文:https://blog.csdn.net/qq_37169817/article/details/79777264 版权声明:本文为博主原创文章,转载请附上博文链接! 1 public class HeapSort { 2…

设计模式 之美 -- 代理模式
文章目录1. 解决问题2. 应用场景1. 业务系统的非功能性开发2. 代理模式在RPC、缓存中的应用3. 实现C实现C语言实现1. 解决问题 客户端和目标对象之间需要进行交互,此时客户端类和目标对象类相关操作之间的逻辑如果交合在一起,会导致客户端和目标对象模块…

java中注解的使用_java中注解的使用
使用过ssh框架的人一定也使用过注解,尤其是在spring框架中,注解可谓是spring容器和AOP编程的重要环节。注解就是用于修饰类、全局变量、方法、参数或局部变量的接口,java中规定,注解的使用不允许影响其修饰类的存在,也…

水题/poj 1852 Ants
1 /*2 PROBLEM:poj18523 AUTHER:Nicole4 MEMO:水题5 */6 #include<cstdio>7 using namespace std;8 int cmax(int a,int b){return a>b?a:b;}9 int cmin(int a,int b){return a<b?a:b;} 10 int main() 11 { 12 int cases; 13 scanf("%d…

素数、最大公约数、最下公倍数、质因数分解
2013-08-18 11:20:43 素数、最大公约数、最下公倍数、质因数分解都是与素数相关的,解决了素数的问题,其他的都可以此为基础求解。 小结: 求1到n之间的素数的基本方法是通过遍历2到sqrt(n),判断每个数是否是素数来得到,…

Spring注解 开发
转载于:https://www.cnblogs.com/JBLi/p/10489541.html

读书:个人成长 -- 即兴演讲
与人交流时,有人发言语无伦次,舌头像打了结。 有人一开讲便滔滔不绝,却毫无重点。 也有人说话索然无味,没法让你投以关注。 如何在任何场合游刃有余地表达? 如何掌控此时此刻,用说话影响他人? …

php mysql环境搭配_centos6.7下搭配apache php mysql环境
安装过程安装apacheapache默认端口为80, 而nginx默认端口也是80, 所以安装apache前, 检查是否安装了nginx, 确保80端口没有被占用, 然后执行以下命令安装apacheyum install httpd httpd-devel启动apache服务/etc/init.d/httpd start或service httpd start停止apache服务/etc/in…

我们如此努力,也不过是个普通人
http://www.nowamagic.net/librarys/eight/posts/2500文 / 張君雅 南方日报曾刊登了一条新闻,大意是说有个女孩子以她的成绩考入北大清华没问题。但她从小参加各种社会活动,深受曾留学法国的母亲“生命的意义在于体验最多而不是最好”影响,决…

Citrix XenServer@cloudstack基本功能测试报告2
Cloudstack功能测试1、创建Zone、Pod、Clusters,添加hosts、Primary Storage、Secondary Storage步骤:1、 登录cloudstack控制板2、 选择基础架构,选择区域,点击查看全部,然后点击添加区域3、 选择基本区域类型4、 输入…

ABP中的Filter(下)
接着上面的一个部分来叙述,这一篇我们来重点看ABP中的AbpUowActionFilter、AbpExceptionFilter、AbpResultFilter这三个部分也是按照之前的思路来一个个介绍,当然这里面如果和前面的Interceptor有重复的部分,那么将会对两者进行一个对比并作出…

LRU算法 -- 链表 完整实现
LRU算法(Least Recently Used) 算是我们经常遇到的一种淘汰算法,其中内存管理模块进行内存页回收时有用到,针对不经常使用的内存页,LRU淘汰策略能够将该内存页回收给操作系统。 属于 我们操作系统设计中的 时间局部性原理,最长时…

python getostime_python中sys,os,time模块的使用(包括时间格式的各种转换)
sys模块sys.argv: 实现从程序外部向程序传递参数。位置参数argv[0]代表py文件本身,运行方法 python xx.py 参数1,参数2 。。self sys.argv[0]name sys.argv[1]age sys.argv[2]print self, name, agesys.getdefaultencoding(): 获取系统当前编码&#…

关于SpringMVC和Struts2的区别
1. 与struts2不同 1、 springmvc的入口是一个servlet即前端控制器,而struts2入口是一个filter过虑器。 2、 springmvc是基于方法开发,传递参数是通过方法形参,可以设计为单例或多例(建议单例),struts2是基于类开发,…

DC-RC加固修补型砂浆
DC-RC加固修补型砂浆www.hrbjg.net一、DC-RC加固修补型砂浆的产品特点:1、耐火、耐高温、耐腐蚀、耐老化性能优良。2、强度高,抹灰操作性好。3、与原混凝土结构的粘结性能良好。4、无收缩,基本不会产生裂缝。5、二氧化碳、氯化物等透过性差&a…

类,实例,属性习题
class Restaurant(): def __init__(self,restaurant_name,cuisine_type): self.restaurant_namerestaurant_name self.cuisine_typecuisine_type def describle_restaurant(self): print("打印的第一条消息") print("打印的第…