当设计到多个产品系列的问题时使用抽象工厂模式;
抽象工厂的优缺点不想提,总之我基本不会去用,扩展起来太tm愁人了,增加一个产品要至少增加三个类,修改三个工厂类,之前搞过一次差点烦死我,哎,都怪学艺不精啊~~
OK上代码:
这里建立一个用户表,提供insert和get的功能。建立用户的接口,实现接口。
class User
{
private int nid;
public int ID
{
get
{
return nid;
}
set {
nid = value;
}
}
private string strName;
public string Name
{
get
{
return strName;
}
set
{
strName = value;
}
}
}
interface IUser
{
void inser(User user);
User getUser(int id);
}
class SqlUser:IUser
{
public void inser(User user)
{
Console.WriteLine("在sql中创建一条数据");
}
public User getUser(int id)
{
Console.WriteLine("根据ID得到一条数据");
return null;
}
}
class AceUser:IUser
{
public void inser(User user)
{
Console.WriteLine("在Access中创建一条数据");
}
public User getUser(int id)
{
Console.WriteLine("根据ID得到一条数据");
return null;
}
}
和上面一样
class Department
{
private int nid;
public int ID
{
get
{
return nid;
}
set
{
nid = value;
}
}
private string strName;
public string Name
{
get
{
return strName;
}
set
{
strName = value;
}
}
}
interface IDepartment
{
void inserDepartment(Department department);
Department getDepartment(int id);
}
class SqlDepartment : IDepartment
{
public void inserDepartment(Department department)
{
Console.WriteLine("在sql中创建一条Department数据");
}
public Department getDepartment(int id)
{
Console.WriteLine("根据ID得到一条Department数据");
return null;
}
}
class AceDepartment : IDepartment
{
public void inserDepartment(Department department)
{
Console.WriteLine("在Access中创建一条Department数据");
}
public Department getDepartment(int id)
{
Console.WriteLine("根据ID得到一条Department数据");
return null;
}
}
建立工厂类:
interface IFactory
{
IUser CreatorUser(); //用户
IDepartment CreatorDepartment();//部门
}
class SqlFactory:IFactory
{
public IUser CreatorUser()
{
return new SqlUser();
}
public IDepartment CreatorDepartment()
{
return new SqlDepartment();
}
}
class AceFactory : IFactory
{
public IUser CreatorUser()
{
return new AceUser();
}
public IDepartment CreatorDepartment()
{
return new AceDepartment();
}
}
调用
User user = new User();
IFactory factor = new SqlFactory();
IUser iu = Datebase.CreatorUser();
user.ID=1;
user.Name="sqlserver";
iu.inser(user);
iu.getUser(1);
Department dp = new Department();
dp.ID = 2;
dp.Name = "zhao";
IDepartment id = Datebase.CreatorDepartment();
id.inserDepartment(dp);
id.getDepartment(1);
抽象工厂就是这么回事,会了工厂方法模式,这个基本就会了。如果说是维护代码还好,真的还算方便,如果是扩展,对不起好烦。不过没事咱还能改进(为什么我之前没想到???奇怪。)
class Datebase
{
private static readonly string db = "Sqlserver";//"Access"
public static IUser CreatorUser()
{
IUser result = null;
switch(db)
{
case "Sqlserver":
result = new SqlUser();
break;
case "Access":
result = new AceUser();
break;
}
return result;
}
public static IDepartment CreatorDepartment()
{
IDepartment result = null;
switch (db)
{
case "Sqlserver":
result = new SqlDepartment();
break;
case "Access":
result = new AceDepartment();
break;
}
return result;
}
}
改进:将抽象工厂去掉改为简单工厂使用switch语句进行分别,这样就不用每个类里面使用数据库的时候写 IFactory factor = new SqlFactory();看看调用:
User user = new User();
// IFactory factor = new SqlFactory();
IUser iu = Datebase.CreatorUser();
user.ID=1;
user.Name="sqlserver";
iu.inser(user);
iu.getUser(1);
Department dp = new Department();
dp.ID = 2;
dp.Name = "zhao";
IDepartment id = Datebase.CreatorDepartment();
id.inserDepartment(dp);
id.getDepartment(1);
但是这样做还是不太好,新增数据库种类的话我还是要在case里面加分支。这个时候可以考虑用什么技术呢??反射技术。
格式:Assembly.Load("程序集名称").CreateInstance("命名空间.类名称");//要是还有问什么是程序集名称的我就不管了。。
当然用反射肯定要引用东西的:using System.Reflection;//要引用这个
修改后:
using System.Reflection;//要引用这个
class Datebase
{
private static readonly string AssemblyName = "myFactory";
private static readonly string db = "Sql";
public static IUser CreatorUser()
{
//这里注意有可能程序集名称并不是命名空间,我没改默认是一样的。
string classname = AssemblyName + "." + db + "User";
return (IUser)Assembly.Load(AssemblyName).CreateInstance(classname);
}
public static IDepartment CreatorDepartment()
{
string classname = AssemblyName + "." + db + "Department";
return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(classname);
}
}
调用时一样的;
这样写在更改已存在数据库调用的时候只更改DB名就可以了,如果增加数据库,那就没办法了,加类吧,这叫扩展。如果想不改源码不重新编译就实现数据库的更改,也是可以的,修改配置文件呗。读取配置文件数据库名复制给db。我这里就不写了。。。