抽象工厂模式
前序
“这么晚才回来,都11点了。”大鸟看着刚推门而入的小菜问道。
“嗨,没办法呀,工作忙。”小菜叹气说道。
“怎么会这么忙,加班有点过头了呀。”
“都是换数据库惹的祸呗。”
“怎么了?”
“我本来写好了一个项目,是给一家企业做的电子商务网站,是用SQL Server作为数据库的,应该说上限后除了开始有些小问题,基本都还可以。而后,公司截到另外一家公司类似需求的项目,但这家公司想省钱,租用了一个空间,只能用Access,不能用SQL Server,于是就要求我今天改造原来那个项目的代码。”
“哈哈,你的麻烦来了。”
“是呀,那是相当的麻烦。但开始我觉得很简单呀,因为地球人都知道,SQL Server和Access在ADO.NET上的使用是不同的。我以为只要做一个全体替换就可以了,哪知道,替换后,错误百出。”
“以后你还有的是班要加了。”
“为什么?”
“只要网站要维护,比如修改或增加一些功能,你就得改两个项目吧,至少在数据库中做改动,响应的程序代码都要改,甚至和数据库不想干的代码也要改,你既然有两个不同的版本,两倍的工作量也是必然的。”
“是呀,如果哪天要用Oracle数据库,估计我要改动的地方更多了。”
“那是当然,Oracle的SQL语法与SQL Server的差别更大。你的改动将是空前的。”
最基本的数据访问程序
“你先写一段你原来的数据库访问的做法给我看看。”
“那就用‘新增用户’和‘得到用户’为例吧。”
#include <stdio.h>
class User
{
public:
int id;
char* name;
};
class SqlserverUser
{
public:
void Insert(User* user)
{
printf("在SQL Server中给User表添加一条记录\n");
}
User* GetUser(int id)
{
printf("在SQL Server中根据ID得到User表一条记录\n");
return 0;
}
};
int main()
{
User* user = new User();
SqlserverUser* su = new SqlserverUser();
su->Insert(user);
su->GetUser(1);
delete user;
delete su;
return 0;
}
“我最开始就是这样写的,非常简单。”
“这里之所以不能换数据库,原因就在于SqlserverUser* su = new SqlserverUser();使得su这个对象被框死在SQL Server上了。如果这里是灵活的,专业点的说法,是多态的,那么在执行‘su->Insert(user);’和‘su->GetUser(1);’时就不用考虑是在用SQL Server还是在用Access了。”
用工厂方法模式的数据访问程序
#include <stdio.h>
class User
{
public:
int id;
char* name;
};
class IUser
{
public:
virtual void Insert(User* user)=0;
virtual User* GetUser(int id)=0;
};
class SqlserverUser : public IUser
{
public:
virtual void Insert(User* user)
{
printf("在SQL Server中给User表添加一条记录\n");
}
virtual User* GetUser(int id)
{
printf("在SQL Server中根据ID得到User表一条记录\n");
return 0;
}
};
class AccessUser : public IUser
{
public:
virtual void Insert(User* user)
{
printf("在Access中给User表添加一条记录\n");
}
virtual User* GetUser(int id)
{
printf("在Access中根据ID得到User表一条记录\n");
return 0;
}
};
class IFactory
{
public:
virtual IUser* CreateUser()=0;
};
class SqlServerFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new SqlserverUser();
}
};
class AccessFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new AccessUser();
}
};
int main()
{
User* user = new User();
IFactory* factory = new SqlServerFactory();
IUser* iu = factory->CreateUser();
iu->Insert(user);
iu->GetUser(1);
delete user;
delete factory;
delete iu;
return 0;
}
“非常好。现在如果要换数据库,只需要把new SqlServerFactory()改成new AccessFactory(),此时由于多态的关系,使得声明IUser接口的对象iu实现根本不知道是在访问哪个数据库,却可以在运行时很好的完成工作,这就是所谓的业务逻辑与数据访问的解耦。”
“但是,大鸟,这样写,代码里还是有指明‘new SqlServerFactory()’呀,我要改的地方,依然很多。”
“这个先不急,待会再说,问题没有完全解决,你的数据库里不可能只有一个User表吧,很可能有其他表,比如增加部门表(Department表),此时如何办呢?”
抽象工厂模式
客户类和工厂类分开。消费者任何时候需要某套产品集合时,只需向抽象工厂请求即可。抽象工厂会再向具体的工厂生产出符合产品集规格的产品。
实现方式(UML类图)
实现代码
#include <stdio.h>
class User
{
public:
int id;
char* name;
};
class Department
{
public:
int id;
char* deptname;
};
// User表接口
class IUser
{
public:
virtual void Insert(User* user)=0;
virtual User* GetUser(int id)=0;
};
// Department表接口
class IDepartment
{
public:
virtual void Insert(Department* department)=0;
virtual Department* GetDepartment(int id)=0;
};
class SqlserverUser : public IUser
{
public:
virtual void Insert(User* user)
{
printf("在SQL Server中给User表添加一条记录\n");
}
virtual User* GetUser(int id)
{
printf("在SQL Server中根据ID得到User表一条记录\n");
return 0;
}
};
class AccessUser : public IUser
{
public:
virtual void Insert(User* user)
{
printf("在Access中给User表添加一条记录\n");
}
virtual User* GetUser(int id)
{
printf("在Access中根据ID得到User表一条记录\n");
return 0;
}
};
class SqlserverDepartment : public IDepartment
{
public:
virtual void Insert(Department* department)
{
printf("在SQL Server中给Department表增加一条记录\n");
}
virtual Department* GetDepartment(int id)
{
printf("在SQL Server中根据ID得到Department表一条记录\n");
return 0;
}
};
class AccessDepartment : public IDepartment
{
public:
virtual void Insert(Department* department)
{
printf("在Access中给Department表增加一条记录\n");
}
virtual Department* GetDepartment(int id)
{
printf("在Access中根据ID得到Department表一条记录\n");
return 0;
}
};
// IFactory接口
class IFactory
{
public:
virtual IUser* CreateUser()=0;
virtual IDepartment* CreateDepartment()=0;
};
class SqlServerFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new SqlserverUser();
}
virtual IDepartment* CreateDepartment()
{
return new SqlserverDepartment();
}
};
class AccessFactory : public IFactory
{
public:
virtual IUser* CreateUser()
{
return new AccessUser();
}
virtual IDepartment* CreateDepartment()
{
return new AccessDepartment();
}
};
int main()
{
User* user = new User();
Department* dept = new Department();
IFactory* factory = new AccessFactory();
IUser* iu = factory->CreateUser();
iu->Insert(user);
iu->GetUser(1);
IDepartment* id = factory->CreateDepartment();
id->Insert(dept);
id->GetDepartment(1);
delete user;
delete dept;
delete factory;
delete iu;
delete id;
return 0;
}
运行结果
所有文件打包下载
posted on 2011-06-26 22:19
lwch 阅读(3323)
评论(2) 编辑 收藏 引用 所属分类:
设计模式