抽象工厂模式:
提供一个创建一系列相关或相互依赖对象的接口,而无需制定他们具体的类。
现实联想:
抽象工厂模式就好像是工厂模式的再一次细化。这次细化的是工厂模式中的各个生产线。举个例子,比如说是一个手机充电器的生产工厂。在工厂模式中,他们的生产线是这样的:充电器,充电线,充电线的接口;而在抽象工厂中他们的生产线是这样的:充电器(虚类或是接口)——快充充电器、慢充充电器;充电线(虚类或是接口)——快充充电线、慢充充电线;充电线接口(虚类接口类)——安卓接口、typec接口。 然后就会有一个工厂虚类或者接口,下面链接两个工厂——快充充电器工厂、慢充充电器工厂。
何时使用抽象工厂模式
在使用抽象工模式的时候,要考虑的是我们的生产线(充电器等等)是否是固定的,如果是固定的就可以使用简单工厂模式的工厂方式,只有一个工厂,使用switch语句选择用哪个工厂。而如果生产线是变化的,那就用工厂模式的工厂,将各个分工厂写成子类。
实例:当我们的用户提出要用两个或者两个以上的数据库系统的时候。
第一步:确定要访问的数据库的表
class User
{
private int _id
;
public int Id
{
get
{return _id
;}
set
{_id
= value
;}
}
private string _name
;
public string Name
{
get
{ return _name
; }
set
{ _name
= value
; }
}
}
访问Department表
class Department
{
private int _id
;
public int Id
{
get
{ return _id
; }
set
{ _id
= value
; }
}
private string _name
;
public string Name
{
get
{ return _name
; }
set
{ _name
= value
; }
}
}
第二步:分别建立两个不同数据库系统访问单个表的的生产线
interface IUser
{
void Insert(User user
);
User
GetUser(int id
);
}
class SqlserveerUser : IUser
{
public void Insert(User user
)
{
Console
.WriteLine("在Sql Server 中给User表增加一条记录");
}
public User
GetUser(int id
)
{
Console
.WriteLine("在sql server中根据ID得到User表一条记录");
return null
;
}
}
class AccessUser:IUser
{
public void Insert(User user
)
{
Console
.WriteLine("在Access 中给User表增加一条记录");
}
public User
GetUser(int id
)
{
Console
.WriteLine("在Access中根据ID得到User表一条记录");
return null
;
}
}
interface Idepartment
{
void Insert(Department departmeent
);
Department
GetDepartment(int id
);
}
class SqlserveerDepartment:Idepartment
{
public void Insert(Department department
)
{
Console
.WriteLine("在Sql Server 中给Department表增加一条记录");
}
public Department
GetDepartment(int id
)
{
Console
.WriteLine("在sql server中根据ID得到Department表一条记录");
return null
;
}
}
class AccessDepartment : Idepartment
{
public void Insert(Department department
)
{
Console
.WriteLine("在Access 中给Department表增加一条记录");
}
public Department
GetDepartment(int id
)
{
Console
.WriteLine("在Access中根据ID得到department表一条记录");
return null
;
}
}
第三步:建立工厂
class DataAccess
{
private static readonly string db
="Sqlserver";
public static IUser
CreatUser()
{
IUser result
= null
;
switch (db
)
{
case "Sqlserver":
result
= new SqlserveerUser();
break;
case "Access":
result
= new AccessUser();
break;
}
return result
;
}
public static Idepartment
CreateDepartment()
{
Idepartment result
= null
;
switch (db
)
{
case "Sqlserver":
result
= new SqlserveerDepartment();
break;
case "Access":
result
= new AccessDepartment();
break;
}
return result
;
}
}
第四步:
客户端代码
User user
= new User() ;
Department dept
= new Department();
IUser iu
= DataAccess
.CreatUser();
iu
.Insert(user
);
iu
.GetUser(1);
Idepartment id
= DataAccess
.CreateDepartment();
id
.Insert(dept
);
id
.GetDepartment(1);
Console
.Read();
反射:
应用的命名空间:using System.Reflection; 例子Iuser result=(Iuser)Assembly.Load(“抽象工厂模式”).CreateInstance(“抽象工厂模式.sqlserverUser”) 反射得到的结果一般都是一个类,所以要决定好要反射那个类,并确定该类的类型,同时要用相应的类接收反射结果。 反射的作用是实例化一个对象,相比较普通写法,反射更加灵活因为className是字符串形态存在的,所以可以在字符创上动手脚,让代码更加灵活。
Using System
.Reflection
;
Class
DateAccess
{
private static readonly string AssemblyName
= "抽象工厂模式";
public static IUser
CreatUser()
{
string classname
= "抽象工厂模式.SqlserveerUser" ;
IUser result
=(IUser
)Assembly
.Load(AssemblyName
).CreateInstance(classname
);
}
public static Idepartment
CreateDepartment()
{
string className
="抽象工厂模式.SqlserveerDepartment";
return (Idepartment
)Assembly
.Load(AssemblyName
).CreateInstance(className
);
}
}