首页 > 设计模式 之美 -- 建造者模式

设计模式 之美 -- 建造者模式

文章目录

        • 1. 解决问题
        • 2. 应用场景
        • 3. 实现
          • C语言实现
          • C++实现
        • 4. 缺点

1. 解决问题

描述如下场景:

  • 类的数据成员很多(8个以上),当我们进行初始化的时候放在初始化列表中,影响类的可读性,同时校验初始化参数列表是否有效的逻辑也无处放置
  • 假如初始化列表中的参数有一定的依赖关系,比如数据成员max 一定比 数据成员min 小才行,这样的依赖关系设置逻辑无处安放(需要在类实例化的时候就要完成依赖关系的创建)
  • 类的对象是不可变的,也就是对象在创建好之后就不能再修改其内部的属性值。此时,我们不能对外暴露类的set成员函数。

针对以上三种关于 类实例化过程中遇到 的问题,我们可以使用建造者模式 解决。

2. 应用场景

  • 一种类的设计较为复杂,需要通过设置不同的可选错参数,定制化地创建不同的对象

建造者模式和工厂模式的区别:

工厂模式:创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象

建造者模式:创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象

举例:

顾客走进餐馆点餐,我们使用工厂模式 根据用户的不同选择,制作不同的食物:汉堡,沙拉,披萨等。

对于披萨来说,用户可以有不同的配料选择:奶酪,西红柿,起司。此时我们通过建造者模式根据用户选择的不同配料制作披萨。

3. 实现

C语言实现

实现功能:

建造者模式实现简单的电脑组装,通过配置不同的config来组装出不同用户要求的电脑(稳定性高、性能高)

#include 
#include 
#include 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 :
");my_personal_computer = builder_safty_config();printf("cpu: %s
", my_personal_computer->cpu);printf("memory: %s
", my_personal_computer->memory);printf("harddisk: %s
", my_personal_computer->harddisk);printf("fast style is :
");my_personal_computer = builder_fast_config();printf("cpu: %s
", my_personal_computer->cpu);printf("memory: %s
", my_personal_computer->memory);printf("harddisk: %s
", 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 
#include 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. 缺点

  • 工厂模式:创建拥有相关性的不同对象(继承同一父类或者接口的子类),由给定的参数来决定创建哪一种类的对象

  • 建造者模式:创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

综上,建造者模式仅仅是为了适配不同需求的对象,并不负责之后对象的处理;工厂模式则主要是针对接口开发,通过创建拥有相关性的不同对象来进行不同的操作。

更多相关:

  • /*判断屏幕宽高比是否为16:9*/ function isScreen16to9() {return window.screen.height / window.screen.width === 9 / 16; }...

  • /*关闭、刷新、跳转、离开当前网页前提示*/ onbeforeunload = function () {return false; };  ...

  • let json = {/**判断JSON格式*/ isJSON: function (str) {if (typeof str == "string") {try {var obj = JSON.parse(str);if (typeof obj == "object" && obj) {return true;} else {...

  •   项目结构   index.js //必须要安装否则就别想运行了❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤ //npm i body-parser -D & cnpm i express & cnpm i node-xlsx & cnp...

  • 一、递归 函数    为什么要有函数,提高代码的可读性,避免重复的代码,提高代码的复用性      在函数中能用return的不要print 1、递归的最大深度997 def foo(n):print(n)n+=1foo(n) foo(1) 递归的最大深度 2、修改递归的最大深度     由此我们可以看出,未报错之前能看到的最大数...