【设计模式】——简单工厂、工厂方法和抽象工厂

时间:2022-10-02 18:14:46

         简单工厂模式、工厂方法模式、抽象工厂模式均属于创建型模式,三种模式都不需要知道具体的类是什么。我们掌握一种思想,就是在创建对象的时候,把容易改变的地方封装起来,来控制变化,更好的适应客户的需求,项目的扩展和变化。

简单工厂模式

   又叫静态工厂模式,顾名思义,用来实例化目标类的静态类。不属于GOF 23种设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。是模式中最简单实用的模式。有利于软件整个体系结构的优化。其最大的优点在于工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。但是违背了开放—封闭原则。(详见上篇博客)

工厂方法模式

  定义一个用于创建对象的接口,让子类决定实例化那一个类。工厂方法使一个类的实例化延迟到其子类。其意义在于定义一个创建产品对象工厂的接口,在接口作为核心工厂不再负责产品的具本创建。核心类成为一个抽象工厂角色,负责具本工厂子类必须实现的接口。而子类实现完成实际的创建工作。是最典型的模板方法模式应用。优点它实现了OCP原则,实现可扩展,层次结构更加复杂,可应用于产品结果复杂的场合。
 //例子,新增用户和得到用户为例。举SQL的例子,Access同理。
//IUser接口,用于客户端访问,解除与具体数据库访问的耦合。
interface IUser
{
void Insert(User user);
User GetUser(int id);
}
//SqlserverUser类,用于访问SQL Sever的User
class SqlserverUser:IUser
{
public void Insert(User user)
{
Console.WriteLine("在SQL Sever中给User表添加一条记录");
}
public User GetUser(int id)
{
Console.WriteLine("在SQL Sever中根据ID得到User表一条记录");
return null;
}
}
//IFactory接口,定义一个创建访问User表对象的抽象的工厂接口
interface IFactory
{
IUser CreateUser();
}
//SqlSeverFactory类,实现IFactory接口,实例化SQLserverUser
class SqlServerFactory:IFactory
{
public IUser CreateUser()
{
return new SqlserverUser ();
}
}
客户端代码:在使用了工厂方法,只需要转换实例化的工厂,由于此时声明的接口对象实现根本不知道在访问哪个数据库,但却可以在运行时很好的完成工作。这就是所谓的业务逻辑与数据访问的解耦。
static void Main(string[] args)
{
User user = new User();
IFactory factory = new SqlServerFactory(); //若要更改Access数据库只需要修改本句即可。
IUser iu = factory.CreateUser();
iu.Insert(user);
iu.GetUser(1);
Console.Read();
}

抽象工厂模式

  提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。抽象工厂最大到的好处就是易于交换产品系列,只需要改变具体工厂即可使用不同的产品配置。第二及时让具体的创建实例过程与客户端分离,客户端是通过他们的丑行接口操纵实例,产品的具体类名也被具体工厂实现分离,不会出现在客户端代码中。没有结合简单工厂使用之前,若要修改增加需求需要修改大量的代码,不符合编程的简单思想。
 //IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合。
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
//SqlserverDepartment类,用于访问SQL Server的Department
class SqlserverDepartment:IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在SQL Server中给Department表增加一条记录");

}
public Department GetDepartment(int id)
{
Console.WriteLine("在SQL Server中根据ID得到Department表一条记录");
return null;
}
}
//AccessDepartment类,用于访问Access的Department.
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 DateAccess
{
private static readonly string db = "Sqlserver";
//private static readonly string db="Access"; //数据库的名称,可以替换成Access,直接显示。
public static IUser CreateUser()
{
IUser result = null;
switch (db) //实例化相应的对象。
{
case "Sqlserver":
result = new SqlserverUser();
break;
case "Access":
result = new AccessUser();
break;
}
return result;
}
public static IDepartment CreateDepartment()
{
IDepartment result = null;
switch (db )
{
case "Sqlserver":
result = new SqlserverDepartment();
break;
case "Access":
result = new AccessDepartment();
break;
}
return result;
}
}
static void Main(string[] args)//客户端代码
{
User user = new User();
Department dept = new Department();
IUser iu = DateAccess.CreateUser(); //直接得到实际的数据库访问实例,而不存在任何依赖。
iu.Insert(user);
iu.GetUser(1);
IDepartment id = DateAccess.CreateDepartment(); //直接得到实际的数据库访问实例,而不存在任何的依赖。
id.Insert(dept);
id.GetDepartment(1);
Console.Read();
}

小结

   其实,无论是简单工厂模式、工厂模式还是抽象工厂模式,它们本质上都是将不变的部分提取出来,将可变的部分留作接口,以达到最大程度上的复用。究竟用哪种设计模式更适合,这要根据具体的业务需求来决定。