###定义
建造模式标准定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,Builder模式与抽象工厂模式很在功能是很相似,都是创建大的复杂的对象,但是它们的区别也有:前者主要是强调一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中的对象不是直接返回的,而抽象工厂模式中对象是直接返回的,它重点强调的是为创建多个相互依赖的对象提供一个统一的接口。
###解释
Builder模式属于创建性模式,它就是将产品的内部表象和产品的生成过程开来,从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程。建造模式就是解决这类问题的一种思想方法——将一个复杂对象的构建与它的表示分离.使得同样的构建过程可以创建不同的表示。Builder结构如图所示。
###适用性:
在以下情况使用builder模式
• 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式(具体的构造细节)时。
• 当构造过程必须允许被构造的对象有不同的表示时。
###举一个例子
一般的应用软件都要进行数据库存储,可能有多份数据,存储在多种数据库,具体的连接,获取表操作等可能不一样。但是每种数据库都是由表组成,每个表由都是由字段组成,因此它们的构造过程是相同。
//字段
class Field
{
public:
Field(int fieldType, const std::string fieldName);
~Field(){}
int type; //字段类型
std::string fieldName; //字段名称
};
//表
class FieldSet
{
public:
bool addField(int fieldType, const std::string &fieldName);
bool addField(Field *field);
const char* getTableName() const
{
return tableName.c_str();
}
protected:
std::vector<Field*> fields;
std::string tableName;
};
//数据库
class zDataBases
{
public:
static zDataBases* instance(std::string type)
{
//是什么type的数据库就实例化什么类型的子类数据库
}
virtual ~zDataBases(){}
private:
zDataBases(){}
public:
virtual bool init(const std::string &url) = 0;
FiledSet *getFields(const std::string &tableName);
protected:
std::map<std::string, FieldSet*> tables;
};
//如果我们使用的是mysql数据库
class MySqlDataBase : public zDataBases
{
//初始化表结构
//建立数据库连接,并取得该数据库所有表的表结构
bool init(const std::string &url, DWORD hashcode = 0);
{
UrlInfo urlInfo(hashcode, url, false);
if(!this->loadDataFromDB(urlInfo))
return false;
return true;
}
//通过指定的连接,载入数据表结构
bool loadDataFromDB(const UrlInfo &url);
{
MYSQL *mysql_conn = NULL;
MYSQL_RES* table_res = NULL;
mysql_conn = mysql_init(NULL);
if(mysql_conn == NULL)
{
//init mysql error
return false;
}
if(!mysql_real_connect(mysql_conn, url.host, url.user, url.passwd, url.dbName, url.port, NULL, CLIENT_COMPRESS | CLIENT_INTERACTIVE))
{
return false;
}
//连接成功
if(mysql_conn)
{
if((table_res = mysql_list_tables(mysql_conn, NULL)) == NULL)
{
if(table_res)
mysql_free_result(table_res);
if(mysql_conn)
mysql_close(mysql_conn);
return false;
}
MYSQL_ROW row;
while((row = mysql_fetch_row(tables_res)))
this->addNewTable(mysql_conn, row[0]);
mysql_free_result(table_res);
}
if(mysql_conn)
mysql_close(mysql_conn);
return true;
}
//加入一个新表
bool addNewTable(MYSQL *mysql_conn, const char* tableName);
{
MYSQL_RES *field_res = NULL;
field_res = mysql_list_fields(mysql_conn, tableName, NULL);
if(field_res)
{
DWORD num_fields = mysql_num_fields(field_res);
MYSQL_FIELD* mysql_fields = NULL;
mysql_fields = mysql_fetch_fields(field_res);
FieldSet *fields = new FieldSet(tableName);
if(!fields)
{
mysql_free_result(field_res);
return false;
}
for(unsigned int i = 0; i < num_fields; ++i)
{
if(!fields->addField(mysql_fields[i].type, mysql_fields[i].name))
{
mysql_free_result(field_res);
return false;
}
}
tables.insert(valueType(tableName, fields));
mysql_free_result(field_res);
}
else
return false;
return true;
}
};
上面代码只有一种数据库,实际上可以是各种类型的数据库,只要实现init即可
总结一下建造模式:
1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个B u i l d e r都相对独立,而与其它的B u i l d e r无关。
3、可使对构造过程更加精细控制。
4、将构建代码和实现代码分开。
5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动