前言
抽象工厂模式,简单工厂(点我呀~),工厂方法模式(点我呀)。这三个概念的掌握以及区别。
抽象工厂模式
英文:Abstract Factory
what
提供一个创建一系列相关或依赖对象的接口,而无需指定它们具体的类。
结构图
IFactory:
是一个抽象工厂接口,它里面应该包含所有的产品创建的抽象方法。
concretefactory1:
是具体的工厂,,为创建不同的产品对象,客户端应使用不同的具体工厂。
情景走向
- 基本的数据访问程序:sqlserverUser se = new sqlserveruser()使得se这个对象被框死在SQLserver上。如何将这个改变成灵活的,多态的?
使用工厂方法模式的数据访问程序:结构图如下,增加接口和工厂
定义一个用于创建对象的接口,让子类决定实例化哪一类。
用抽象工厂模式的数据访问程序,结构图如下,增加具体部门表的处理。
IDepartment接口,用户客户端访问,解除与具体数据库访问的耦合。
4. 反射+抽象工厂的数据访问程序
5. 反射+配置文件实现数据访问程序
优缺点
优点:
1. 易于交换产品系列。由于具体工厂类,在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同 产品配置。
2. 它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。
3. 良好运用了开放-封闭原则,依赖倒转原则。
缺点:
增加新的产品等级结构很复杂,需要修改抽象工厂和所有的具体工厂类,对“开放-封闭原则”的支持呈现倾斜性
代码展示
用户类:
//用户类
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; }
}
}
//sqlserverUser类,用于访问sql的user
class sqlserverUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在sql中给User表添加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在sql中根据ID得到user表一条记录");
return null;
}
}
//AccessUser类,用于访问access的user,同上↑
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 IUser //接口
{
void Insert(User user);
User GetUser(int id);
}
抽象工厂接口:
//定义一个创建访问department表对象的抽象的工厂接口。
interface IFactory //抽象工厂接口
{
IUser CreateUser();
IDepartment CreateDepartment(); //增加的接口方法
}
具体工厂类:
//sqlServerFactory类,实现IFactory接口,实例化sqlserverUser和SqlserverDepartment
class sqlServerFactory:IFactory
{
public IUser CreateUser()
{
return new sqlserverUser();
}
public IDepartment CreateDepartment() //增加了sqlserverdepartment工厂
{
return new SqlserverDepartment();
}
}
//AccessFactory类,实现IFactory接口,实例化AccessUser和AccessDepartment
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
public IDepartment CreateDepartment() //增加了sqlserverdepartment工厂
{
return new AccessDepartment();
}
}
增加表类:
class Department
{
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
private string _deptName;
public string DeptName
{
get { return _deptName; }
set{_deptName = value ;}
}
}
表类接口:
//IDepartment接口,用户客户端访问,解除与具体数据库访问的耦合
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
具体数据库类:
//用于访问SQL的Department
class SqlserverDepartment:IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在SQL中给Department表中增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在SQL中根据ID得到department表一条记录");
return null;
}
}
//用于访问Acess的Department
class AccessDepartment:IDepartment //同SQL类
{
public void Insert(Department department)
{
Console.WriteLine("在Access中给Department表中增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在Access中根据ID得到department表一条记录");
return null;
}
}
客户端代码:
class Program
{
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
//只需确定实例化哪一个数据库访问对象给factory即可(SQL server factory或access factory)
IFactory factory = new AccessFactory();
IUser iu = factory.CreateUser(); //此时已与具体的数据库访问解除了依赖
iu.Insert(user);
iu.GetUser(1);
IDepartment id = factory.CreateDepartment();
id.Insert(dept);
id.GetDepartment(1);
id.GetDepartment(1);
Console.Read();
}
}
效果图:
拓展
格式:
反射技术的格式是: Assembly.Load(“程序集名称”).CreateInstance(“命名空间.类名称”)
需要引用using system.Reflection;这个命名空间
具体:略
后记
这个模式的一个重点就是区别开与简单工厂,工厂方法模式的不同。
难点就是容易混淆诸多类,要先缕清结构图,再去进行代码敲写。
逻辑关系很重要!