简单工厂,工厂方法,抽象工厂都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,优化了系统的架构,并且增强了系统的扩展性。
本文是本人对这三种模式学习后的一个小结以及对他们之间的区别的理解。
简单工厂
简单工厂模式的工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的对象实例。
不修改代码的话,是无法扩展的。
工厂方法
工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。
在同一等级结构中,支持增加任意产品。
抽象工厂
抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。
应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。
小结
★工厂模式中,重要的是工厂类,而不是产品类。产品类可以是多种形式,多层继承或者是单个类都是可以的。但要明确的,工厂模式的接口只会返回一种类型的实例,这是在设计产品类的时候需要注意的,最好是有父类或者共同实现的接口。
★使用工厂模式,返回的实例一定是工厂创建的,而不是从其他对象中获取的。
★工厂模式返回的实例可以不是新创建的,返回由工厂创建好的实例也是可以的。
区别
简单工厂 : 用来生产同一等级结构中的任意产品。(对于增加新的产品,无能为力)
工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
抽象工厂:用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
以上三种工厂 方法在等级结构和产品族这两个方向上的支持程度不同。所以要根据情况考虑应该使用哪种方法。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/superbeck/archive/2009/08/14/4446177.aspx
假想场景:hp和apple是全球知名的电脑生产厂家,他们各自的电脑操作系统分别是windows和macintosh,microsoft是软件行业的龙头。为了吸引更多客户购买电脑,hp和apple请ms为他们开发两款最常用的软件,办公软件和及时通讯工具。ms结了订单后,分别为hp和apple开发了office和msn。
上面的场景其实蕴含着我们常见的设计模式思维方式,code is cheap,代码来了。
一:简单工厂
view plaincopy to clipboardprint?
using System;
//ms的产品
public class Software
{
private string softwareName;
public virtual string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
public string GetSoftwareName()
{
return softwareName;
}
}
//ms的产品:office
public class Office:Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Office";
return “Office”;
}
}
//ms的产品:msn
public class Msn : Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Msn";
return “Msn”;
}
}
/// <summary>
/// 简单工厂
/// </summary>
public class MsSoftwareFactory
{
public static Software CreateSoftware(string softwareName)
{
Software msSoftware = null;
switch (softwareName)
{
default:
break;
case "office":
msSoftware = new Office();
break;
case "msn":
msSoftware = new Msn();
break;
}
return msSoftware;
}
}
/// <summary>
/// 客户端调用
/// </summary>
public class Client {
static void Main(string[] args)
{
Software msSoftware = MsSoftwareFactory.CreateSoftware("office");
Console.WriteLine(msSoftware.GetSoftwareName());
}
}
using System;
//ms的产品
public class Software
{
private string softwareName;
public virtual string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
public string GetSoftwareName()
{
return softwareName;
}
}
//ms的产品:office
public class Office:Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Office";
return “Office”;
}
}
//ms的产品:msn
public class Msn : Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Msn";
return “Msn”;
}
}
/// <summary>
/// 简单工厂
/// </summary>
public class MsSoftwareFactory
{
public static Software CreateSoftware(string softwareName)
{
Software msSoftware = null;
switch (softwareName)
{
default:
break;
case "office":
msSoftware = new Office();
break;
case "msn":
msSoftware = new Msn();
break;
}
return msSoftware;
}
}
/// <summary>
/// 客户端调用
/// </summary>
public class Client {
static void Main(string[] args)
{
Software msSoftware = MsSoftwareFactory.CreateSoftware("office");
Console.WriteLine(msSoftware.GetSoftwareName());
}
}
上面的简单工厂在一个方法体中有个switch...case,违背了“对扩展开放,对修改封闭”的原则,即“开放-封闭原则”。下面的工厂方法就克服了简单工厂的缺点,降低了客户端程序和产品对象的耦合。
二:工厂方法 (设计原则:要依赖抽象,不要依赖具体类)
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
view plaincopy to clipboardprint?
using System;
//ms的产品
public class Software
{
private string softwareName;
public string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
public virtual string GetSoftwareName()
{
return softwareName;
}
}
//ms的产品:office
public class Office:Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Office";
return "Office";
}
}
//ms的产品:msn
public class Msn : Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Msn";
return "Msn";
}
}
interface ISoftwareFactory
{
Software CreateSoftware();
}
/// <summary>
/// office工厂
/// </summary>
public class OfficeFactory:ISoftwareFactory
{
public Software CreateSoftware()
{
return new Office();
}
}
/// <summary>
/// msn工厂
/// </summary>
public class MsnFactory : ISoftwareFactory
{
public Software CreateSoftware()
{
return new Msn();
}
}
/// <summary>
/// 客户端调用
/// </summary>
public class Client {
static void Main(string[] args)
{
ISoftwareFactory factory = new OfficeFactory();
Software msSoftware = factory.CreateSoftware();
Console.WriteLine(msSoftware.GetSoftwareName());
}
}
using System;
//ms的产品
public class Software
{
private string softwareName;
public string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
public virtual string GetSoftwareName()
{
return softwareName;
}
}
//ms的产品:office
public class Office:Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Office";
return "Office";
}
}
//ms的产品:msn
public class Msn : Software
{
public override string GetSoftwareName()
{
this.SoftwareName = "Msn";
return "Msn";
}
}
interface ISoftwareFactory
{
Software CreateSoftware();
}
/// <summary>
/// office工厂
/// </summary>
public class OfficeFactory:ISoftwareFactory
{
public Software CreateSoftware()
{
return new Office();
}
}
/// <summary>
/// msn工厂
/// </summary>
public class MsnFactory : ISoftwareFactory
{
public Software CreateSoftware()
{
return new Msn();
}
}
/// <summary>
/// 客户端调用
/// </summary>
public class Client {
static void Main(string[] args)
{
ISoftwareFactory factory = new OfficeFactory();
Software msSoftware = factory.CreateSoftware();
Console.WriteLine(msSoftware.GetSoftwareName());
}
}
工厂方法的缺点是每加一个产品,就要创建一个对应的产品工厂类,增加了额外的开发量。
三、抽象工厂
提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。
抽象工厂最经典的应用莫过于数据库访问程序。网上有很多这方面的讨论。不多说了。这里我继续用开篇讲的场景来描述。
我们知道office和msn根据操作系统的不同可以分为windows版本的和mac版本的,也许还有linux,unix版本的,归根结底,这里的产品涉及到产品系列的问题,抽象工厂可以解决这个问题:
view plaincopy to clipboardprint?
using System;
//ms的产品:office
public class Office
{
private string softwareName;
public string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
}
public interface IOffice
{
Office GetOffice();
}
//ms的windows版本Office
public class WinOffice : IOffice
{
public Office GetOffice()
{
return new Office();
}
}
//ms的macintosh版本Office
public class MacOffice : IOffice
{
public Office GetOffice()
{
return new Office();
}
}
//ms的产品:msn
public class Msn
{
private string softwareName;
public string SoftwareName
{
get { return softwareName; }
set { softwareName = value; }
}
}
public interface IMsn
{
Msn GetMsn();
}
//ms的windows版本msn
public class WinMsn:IMsn
{
public Msn GetMsn()
{
return new Msn();
}
}
//ms的macintosh版本msn
public class MacMsn : IMsn
{
public Msn GetMsn()
{
return new Msn();
}
}
interface ISoftwareFactory
{
IOffice CreateOffice();
IMsn CreateMsn();
}
/// <summary>
/// windows版本的工厂
/// </summary>
public class WindowsFactory:ISoftwareFactory
{
public IOffice CreateOffice()
{
return new WinOffice();
}
public IMsn CreateMsn()
{
return new WinMsn();
}
}
/// <summary>
/// macintosh版本的工厂
/// </summary>
public class MacFactory : ISoftwareFactory
{
public IOffice CreateOffice()
{
return new MacOffice();
}
public IMsn CreateMsn()
{
return new MacMsn();
}
}
/// <summary>
/// 客户端调用
/// </summary>
public class Client {
static void Main(string[] args)
{
ISoftwareFactory factory = new WindowsFactory();
IOffice office = factory.CreateOffice();
IMsn msn = factory.CreateMsn();
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gisfarmer/archive/2009/03/15/3992382.aspx