工厂模式分为三种:简单工厂模式,工厂模式和抽象工厂模式。
定义:
简单工厂模式:用一个单独的类来做创造实例的过程。
工厂模式:一个用于创建对象的接口,让子类决定实例化哪一个类,讲一个类的实例化
延迟到其子类。
抽象工厂模式:为创建一组相关或相互依赖的对象的类,而不指定具体类。
结构图:
这是简单工厂的结构图,从图中就很好理解。
简单工厂的优点:
根据用户需要,new出需要的对象。
但是简单工厂弊端:
当新加入一个功能是,就要修改工厂。这个时候,就需要工厂模式了。
从图中我们可以看出:
工厂模式客服了修改工厂类,运用扩展,加一个算法工厂,就行了。
工厂模式的有点:典型的解耦和模式。
这个就是抽象工厂,最核心的思想就是:抽象出接口类和抽象类,实现化不同的子类。
使用场景:
在数据库访问中,在SQLserver中有User和Department两张表,在Access中也有同样的
同样的两张表,现在,需要向不同的数据库中代码访问User表,进行添加数据和查询数据的方法。
分析:
怎样做到最高效率的在SQLServer和Access中进行转换时我们需要考虑的。
第1版代码:不加如何模式
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; }
}
}
class SqlserverUser
{
public void Insert(User user)
{ Console.WriteLine("在SQL Server中给User表添加一条记录"); }
public User GetUser(int id)
{
Console.WriteLine("在SQL Server中根据ID得到User表一条记录");
return null;
}
}
客户端:
class Program
{
static void Main(string[] args)
{
User user = new User();
SqlserverUser su = new SqlserverUser();
su.Insert(user);
su.GetUser(1);
Console.Read();
}
}
从代码中我们可以看到,如果我们需要从Access数据库中访问User,则要添加类,修改客户端的代码将SqlserverUser su=new SqlserverUser();这句代码改为SqlAccessUser ac=new SqlAccessUser();这样写就违反了开闭原则。
第2版代码:工厂方法模式的数据访问程序
接口层
interface IFactory//工厂接口,与调用者交互
{
IUser CreateUser();
}
interface IUser//产品接口,定义产品的规范,所有的产品实现都必须遵循产品接口定义规范。
{
void Insert(User user);
User GetUser(int id);
}
上面是两个接口,上面有他们的结构图,一目了然。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。产品接口是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。
实现:
class SqlserverUser : 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 SqlAccessUser : IUser
{
public void Insert(User user)
{
Console.WriteLine("在Access中给User表添加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在Access中根据ID得到User表一条记录");
return null;
}
}
class SqlserverFactory : IFactory//工厂实现,工厂实现决定如何实例化产品,是实现拓展的途径。需要多少中产品,就要有多少个具体的工厂实现。
{
public IUser CreateUser()
{
return new SqlserverUser();
}
}
class SqlAccessFactory : IFactory
{
public IUser CreateUser()
{
return new SqlAccessUser();
}
}
工厂的实现:工厂实现决定如何实例化产品,是实现拓展的途径,需要有多少中产品,就需要有多少个具体的工厂实现。
客户端:
class Program
{
static void Main(string[] args)
{
User user = new User();//实例化实体
IFactory factory = new SqlserverFactory();//实现工厂类
IUser iu = factory.CreateUser();//工厂中创造出想要的对象
iu.Insert(user);
iu.GetUser(1);
Console.Read();
}
}
若要访问Department表,设计到2维操作,我们需要用到抽象工厂:
这里其实很简单,就是加一个Department接口,两个子类继承,加一个实体类,修改工厂类。
由于代码千篇一律,怕大家看烦了,就不晒了。
第3版:抽象模式加简单工厂模式:
结构图:
class DataAccess
{
//private static readonly string db = "Sqlserver";
private static readonly string db = "Access";
public static IUser CreateUser()
{
IUser result = null;//一定是父类
switch (db)
{
case "Sqlserver":
result = new SqlserverUser();
break;
case "Access":
result = new SqlAccessUser();
break;
}
return result;
}
public static IDeparment CreateDep()
{
IDeparment result = null;
switch (db)
{
case "Sqlserver":
result = new SqlserverDeparment();
break;
case "Access":
result = new SqlAccessDepartment();
break;
}
return result;
}
}
客户端:
class Program
{
static void Main(string[] args)
{
User user = new User();
Department dep = new Department();
IUser iu = DataAccess.CreateUser();//创造实例化的子类
iu.Insert(user);
iu.GetUser(1);
IDeparment dept = DataAccess.CreateDep();
dept.Insert(dep);
dept.GetDep(1);
Console.Read();
}
}
以上就是场景分析。
优点:
简单工厂、工厂、抽象工厂是层层递进的关系,但是都存在这有点和缺点,我都在里面说了,所以,这里仅简单介绍一下抽象工厂的优点:
第一:易于交换产品系列,在一个应用中值需要再初始化的时候,出现一次,这就是的改变一个应用的具体工厂变得非常容易,他只需要改变具体工厂即可使用不同的产品配置。
第二:让具体的创建实例过程与客户端分离,客户端是通过他们的抽象接口操纵实例,产品的具体类名也被具体工厂的实现分离,不会出现在客户代码中。