这些天看了很多设计模式方面的文章,自己也动手写了一些demo,逐渐感到接口和多态在软件设计中就像陈年老酒,越喝越香。
下面通过一个小例子来说说抽象工厂在实际中的应用。由于是个人心得笔记,写的可能不会很详细,敬请见谅。
在项目中有时会碰到数据库平台迁移的问题,比如从access迁到sql server平台,在代码中完全可以采用抽象工厂实现。首先我们完成access和sql访问数据库的代码。假设数据库有两张表,user和article,对这两张表的数据库操作接口如下:

IDAL.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
interface IUserDAL
{
string GetUser();
string CreateUser();
}
interface IArticleDAL
{
string GetArticle();
string CreateArticle();
}
}
对该接口的实现有两个类,分别代表对access和sql server的操作。

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
class SqlUserDAL:IUserDAL
{
#region IUserDAL 成员
public string GetUser()
{
return this.ToString();
}
public string CreateUser()
{
return this.ToString();
}
#endregion
}
class SqlArticleDAL : IArticleDAL
{
#region IArticleDAL 成员
public string GetArticle()
{
return this.ToString();
}
public string CreateArticle()
{
return this.ToString();
}
#endregion
}
}

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
class AccessUserDAL:IUserDAL
{
#region IUserDAL 成员
public string GetUser()
{
return this.ToString();
}
public string CreateUser()
{
return this.ToString();
}
#endregion
}
class AccessArticleDAL : IArticleDAL
{
#region IArticleDAL 成员
public string GetArticle()
{
return this.ToString();
}
public string CreateArticle()
{
return this.ToString();
}
#endregion
}
}
客户端如何访问以上两个类呢?显然直接new SqlDal()之类的用法会极大增加类之间的耦合度,这时候接口和多态的用处就体现出来了。以上两个类都继承自IDAL接口,可设计工厂类,调用接口而不用直接调用操作数据库的类。
抽象工厂类如下:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
abstract class DBFactory
{
abstract public IUserDAL CreateUserDAL();
abstract public IArticleDAL CreateArticleDAL();
}
}
具体工厂负责具体对象的创建。

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
class SqlFactory:DBFactory
{
public override IArticleDAL CreateArticleDAL()
{
return new SqlArticleDAL();
}
public override IUserDAL CreateUserDAL()
{
return new SqlUserDAL();
}
}
}
另一个具体工厂类AccessFactory跟SqlFactory类似,这里就不写具体代码了。
客户端测试代码:

Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DBFactory
{
abstract class Program
{
static void Main(string[] args)
{
DBFactory factory = new AccessFactory();
IArticleDAL articleDAL = factory.CreateArticleDAL();
IUserDAL userDAL=factory.CreateUserDAL();
Console.WriteLine(articleDAL.CreateArticle());
Console.WriteLine(articleDAL.GetArticle());
Console.WriteLine();
Console.WriteLine(userDAL.CreateUser());
Console.WriteLine(userDAL.GetUser());
Console.Read();
}
}
}
更改数据库之后,只需把new AccessFactory()改成new SqlFactory()即可。这样写客户端跟具体实现类还是存在耦合度,可使用反射技术,进一步降低耦合度,这里就不继续探讨了。