一、前言:
前段时间介绍解释器模式和适配器模式,今天继续了解工厂模式
二、工厂模式
一、名称:
工厂模式
二:属性:
创建型
三、定义:
定义一个接口,该接口是用于创建对象的,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类。
四、白话:
定义一个接口,该接口是用于创建对象的接口,工厂方法使得类在实例化的时候在子类处开始实例化
五、何时用:
当我们明确的计划不同条件下创建不同实例,需要一个系统有比较好的扩展性的时候
六、作用:
解决接口选择的问题,让子类实现工厂接口,返回的也是一个抽象的产品
七、要素:四个
- 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
- 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
- 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
- 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。
八、优点:
1、一个调用者想创建一个对象,只要知道其名称就可以了
2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以,降低耦合性
3、屏蔽产品的具体实现,调用者只关心铲平的接口,对调用者屏蔽具体的产品变化
4、可以是代码结构清晰,有效的封装变化,
在编程中,产品类的实例化有时候是比较复杂和多变的,通过工厂模式,将产品的实例化封装起来,使得调用者根本无需关心产品的实例化过程,只需依赖工厂即可得到自己想要的产品。
九、不足:
每增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中的类的个数成倍的增加,在一 定的程度上增加了系统的复杂度,同时也增加了具体类的依赖。
十、使用场景:
1、日志记录器:用户可以选择记录到什么地方,如:本地磁盘,系统事件,远程服务器等
2、数据库访问,当用户不知道系统采用那一类数据库,以及数据库可能随时变化时。
3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
4、任何地方需要生成复杂对象的地方,需要引入一个工厂类
5、调用者自己组装产品需要增加依赖关系时
6、当系统有比较好的扩展性时,可以考虑使用,不同的产品用不同的实现工厂来组装
十一、类图:
十二、如何使用:学雷锋
1、创建一个接口
interface IFactory
{
LeiFeng CreateLeiFeng();
}
2、创建两个实现接口的UndergraduateFactory 和 VolunteerFactory实体类
//学雷锋的大学生工厂
class UndergraduateFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Undergraduate();
}
}
//社区志愿者工厂
class VolunteerFactory : IFactory
{
public LeiFeng CreateLeiFeng()
{
return new Volunteer();
}
}
3、创建一个工厂,生成基于给定信息的实体类的对象。
//雷锋
class LeiFeng
{
public void Sweep()
{
Console.WriteLine("扫地");
}
public void Wash()
{
Console.WriteLine("洗衣");
}
public void BuyRice()
{
Console.WriteLine("买米");
}
}
4、使用该工厂,通过传递类型信息来获取实体类的对象
//工厂方法模式
IFactory factory = new UndergraduateFactory();
LeiFeng student = factory.CreateLeiFeng();
IFactory factory1 = new VolunteerFactory();
LeiFeng student1 = factory1.CreateLeiFeng();
student.BuyRice();
student.Sweep();
student.Wash();
Console.Read();
三、抽象工厂
一、名称:
抽象工厂(Abstract Factory)
二、属性:
创建型
三、定义:
为创建一系列相关或相互依赖对象提供一个接口,而且无需指定他们具体的类
四、白话:
创建接口,创建的是具有依赖或关联关系的对象之间的接口,这些接口不用与类打交道只需要和所需要的对象打交道
五、何时用:
系统产品有多于一个的产品族,而系统只消费其中一个族的产品,也就是一个继承体系中,如果存在着多个等级结构(即存在多个抽象类),并且分别属于各个等级结构中的实现类之间存在着一定的关联或者约束
六、作用:
围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。主要解决接口选择问题
七、优点:
当一个产品族中的多个对象被设计成一起工作时(产品族一般或多或少的都存在一定的关联),它能保证客户端始终只使用同一个产品族中的对象
八、不足:
产品族的扩展将是一件十分费力的事情,假如产品族中需要增加一个新的产品,则几乎所有的工厂类都需要进行修改。所以使用抽象工厂模式时,对产品等级结构的划分是非常重要的。
九、使用场景:
一个继承体系中,如果存在着多个等级结构(即存在着多个抽象类),并且分属各个等级结构中的实现类之间存在着一定的关联或者约束,也就是说当创建的对象是一系列相互关联或依赖的产品族时,就可以使用抽象工厂模式,如:QQ换肤,一整套一起换。2。生成不同操作系统的程序。
十、类图:
十二、如何使用:
1、 //IDepartment接口,用于客户端访问,解除与具体数据库访问的耦合
interface IDepartment
{
void Insert(Department department);
Department GetDepartment(int id);
}
2、 //SqlseverDepartment类,用于访问SQL server的Department
class SqlseverDepartment:IDepartment
{
public void Insert(Department department)
{
Console.WriteLine("在SQLSever中给Department表增加一条记录");
}
public Department GetDepartment(int id)
{
Console.WriteLine("在Access中根据ID得到Department表一条记录");
return null;
}
}
3、//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;
}
}
4、 //IFactory接口,定义一个创建访问Department表对象的抽象接口。
interface IFactory
{
IUser CreateUser();
//增加接口方法
IDepartment CreateDepartment();
}
5、//SqlSeverFactory类,实现IFactory接口,实例化SQLserverUser和SqlserverDepartment.
class SqlSeverFactory:IFactory
{
public IUser CreateUser()
{
return new SqlserverUser();
}
public IDepartment CreateDepartment()
{
//增加了SqlserverDepartment工厂
return new SqlseverDepartment();
}
}
6、// AccessFactory类,实现IFactory接口,实例化AccessUser和AccessDepartment.
class AccessFactory : IFactory
{
public IUser CreateUser()
{
return new AccessUser();
}
public IDepartment CreateDepartment()
{
//增加了AccessDepartment工厂
return new AccessDepartment();
}
}
7、//客户端代码
static void Main(string[] args)
{
User user = new User();
Department dept = new Department();
//只需要实例化哪一个数据库访问对象给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);
Console.Read();
}
}
四、对比:
抽象工厂模式与工厂模式的区别:
1、抽象工厂模式是工厂模式的升级版本,它用来创建一组相关或者相互依赖的对象
2、工厂方法针对的是一个产品等级结构,抽象工厂模式则
3、工厂方法模式提供的所有产品都是衍生于同一个接口或抽象类,而抽象工厂模式所提供的产品则是衍生自不同的接口或抽象类。
4、
抽象工厂模式所提供的一系列产品就组成一个产品族;而工厂方法提供的一系列产品称为一个等级结构。
五、补充:
抽象族:是指位于不同产品等级结构中功能相关联的产品组成的家族,