• 定义:

1.) 工厂方法模式是用来封装对象的创建,通过让子类来决定创建的对象是什么,来达到将对象创建的过程封装的目的;

2.) 定义了一个创建对象的接口,但由子类决定要实例的泪是哪一个。工厂方法让类把实例化推迟到子类。

  • 适用场景:

代码中经常会出现:根据条件创建实现了同一个接口的不用类实例,而这些判定条件可能随时变动,导致我们这个不得不去改动很多代码。

备注:简单工厂在Head First中,被认为不是设计模式的一种,但人们经常使用,大家习惯性的叫,久了也就言传为“工厂方法模式”。

  • 简单工厂方法
  • 解决了什么问题

例如:

string dbName=string.Empty;
dbName="Access";
MemberDaoBase memberDao=null; if(dbName.ToUpper()=="ACCESS"){
memberDao=new Access.MemberDao();
}
else if(dbName.ToUpper()=="SQLSERVER")
{
memberDao=new SqlServer.MemberDao();
}
memberDao.Create(new Member());
memberDao.Modify(new Member());
memberDao.Remove();

如果代码中不再变动还好,但这种情况很多时候是不存在的,当来了一个新的领导,领导说Sqlite的性能好且免费,那你就不得不去重新去写一个Sqlite.MemberDao,之后再在这里的判断条件中添加上

 else if(dbName.ToUpper()=="SQLITE")
{
memberDao=new SqlServer.SqliteDao();
}

当某天另外一个领导说我们不再支持SqlServer了,我们就不得不把else if(dbName.ToUpper()=="SQLSERVER") {...} 这块代码给注释了。我们就痛苦在这种“变动”中。

问题分析:

不稳定部分:

 string dbName=string.Empty;
dbName="Access";
MemberDaoBase memberDao=null; if(dbName.ToUpper()=="ACCESS"){
memberDao=new Access.MemberDao();
}
else if(dbName.ToUpper()=="SQLSERVER")
{
memberDao=new SqlServer.MemberDao();
}

稳定部分:

 memberDao.Create(new Member());

 memberDao.Modify(new Member());

 memberDao.Remove();

如果我们将不稳定的部分给交给两外一个类单独管理,就能把这种耦合变得低一点,当我们需要“变动”时,只用去修改这个管理类;而这管理来是用来new 实例的,我们习惯。

  • “new管理类(简单工厂方法核心类)”:
 /// <summary>
/// Description of MemberDaoFactory.
/// </summary>
public class MemberDaoFactory
{
public MemberDaoBase Create(string dbName)
{
if(dbName.ToUpper()=="ACCESS")
{
Console.WriteLine("new Access.MemberDao()");
return new Access.MemberDao();
}
else if(dbName.ToUpper()=="SQLSERVER")
{
Console.WriteLine("new SqlServer.MemberDao()");
return new SqlServer.MemberDao();
}
else
{
throw new NotSupportedException(string.Format("Not supported {0}",dbName));
}
}
}
  • 按照简单工厂方法的定义调整

代码结构图:

Member.cs

 /// <summary>
/// Description of Member.
/// </summary>
public class Member
{
private int id;
private string name; public Member()
{
} public int Id
{
get { return id; }
set{id=value;}
} public string Name
{
get { return name; }
set { name = value; }
}
}

Dao/MemberBO.cs

 using System;

 namespace FactoryMethod
{
/// <summary>
/// Description of MemberBO.
/// </summary>
public class MemberBO
{
private MemberDaoFactory memberDaoFactory=null;
private string dbName=string.Empty; public MemberBO(string dbName,MemberDaoFactory memberDaoFactory)
{
this.dbName=dbName;
this.memberDaoFactory=memberDaoFactory;
} public void Create(Member member)
{
if(member==null)
{
throw new ArgumentNullException("member is null");
} MemberDaoBase memberDao=this.memberDaoFactory.Create(this.dbName); memberDao.Create(member);
}
}
}

Dao/MemberDaoBase.cs

 using System;

 namespace FactoryMethod
{
public abstract class MemberDaoBase
{
public abstract void Create(Member member); public abstract void Modify(Member member); public abstract void Remove(int id);
}
}

Dao/SqlServer/MemberDao.cs

 using System;

 namespace FactoryMethod.SqlServer
{
/// <summary>
/// Description of MemberDao.
/// </summary>
public class MemberDao:MemberDaoBase
{
public MemberDao()
{
} public override void Create(Member member)
{
//...
Console.WriteLine("Insert member into sqlserver db");
} public override void Modify(Member member)
{
//...
Console.WriteLine("modify member from sqlserver db");
} public override void Remove(int id)
{
//...
Console.WriteLine("remove member from sqlserver db");
}
}
}

Dao/Access/MemberDao.cs

 using System;

 namespace FactoryMethod.Access
{
/// <summary>
/// Description of MemberDao.
/// </summary>
public class MemberDao:MemberDaoBase
{
public MemberDao()
{
} public override void Create(Member member)
{
//...
Console.WriteLine("Insert member into access db");
} public override void Modify(Member member)
{
//...
Console.WriteLine("modify member from access db");
} public override void Remove(int id)
{
//...
Console.WriteLine("remove member from access db");
}
}
}

客户端调用:

 class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello World!"); // TODO: Implement Functionality Here
MemberBO memberBO0=new MemberBO("access",new MemberDaoFactory());
memberBO0.Create(new Member()); MemberBO memberBO1=new MemberBO("sqlserver",new MemberDaoFactory());
memberBO1.Create(new Member()); Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}

输出结果:

  • 工厂方法

当系统要求不再是只有普通人员了,分出了管理层和基层,而且程序中要求不同等级的数据放在不同网络上,且数据库中的字段名称不同,但意义还是一样时。

我们当前系统的结构就不能很好的应对了,于是我们就需要这样处理:

提取出对应的抽象MemberBO类,和MemberBO的具体实现类ManagerBO,EmployeeBO,MemberBO包含所有的外部需要的功能外还包含一个抽象的FactoryMethod函数,ManagerBO和EmployeeBO要实现FactoryMethod函数:

对应的类:

  public class Member
{
public Member() { } public int ID { get; set; } public string Name { get; set; }
} public abstract class MemberDaoBase
{
public abstract void Create(Member member); public abstract void Modify(Member member);
} public abstract class MemberBOBase
{
protected virtual void Create(Member member, string dbName)
{
if (member == null)
{
throw new ArgumentNullException("member is null!");
} this.FactoryMethod(dbName).Create(member);
} protected virtual void Modify(Member member, string dbName)
{
if (member == null)
{
throw new ArgumentNullException("member is null!");
} this.FactoryMethod(dbName).Modify(member);
} public abstract MemberDaoBase FactoryMethod(string dbName);
} public class ManagerBO : MemberBOBase
{
public override MemberDaoBase FactoryMethod(string dbName)
{
if (dbName.ToUpper() == "ACCESS")
{
return new ManagerAccessDao();
}
else if (dbName.ToUpper() == "SQLSERVER")
{
return new ManagerSqlServerDao();
}
else
{
throw new NotImplementedException(string.Format("{0} not implemented", dbName));
}
}
} public class EmployeeBO : MemberBOBase
{
public override MemberDaoBase FactoryMethod(string dbName)
{
if (dbName.ToUpper() == "ACCESS")
{
return new EmployeeAccessDao();
}
else if (dbName.ToUpper() == "SQLSERVER")
{
return new EmployeeSqlServerDao();
}
else
{
throw new NotImplementedException(string.Format("{0} not implemented", dbName));
}
}
} public class ManagerAccessDao : MemberDaoBase
{
public override void Create(Member member)
{
throw new NotImplementedException();
} public override void Modify(Member member)
{
throw new NotImplementedException();
}
} public class ManagerSqlServerDao : MemberDaoBase
{
public override void Create(Member member)
{
throw new NotImplementedException();
} public override void Modify(Member member)
{
throw new NotImplementedException();
}
} public class EmployeeAccessDao : MemberDaoBase
{
public override void Create(Member member)
{
throw new NotImplementedException();
} public override void Modify(Member member)
{
throw new NotImplementedException();
}
} public class EmployeeSqlServerDao : MemberDaoBase
{
public override void Create(Member member)
{
throw new NotImplementedException();
} public override void Modify(Member member)
{
throw new NotImplementedException();
}
}
  • 简单工厂和工厂方法之间的差异

简单工厂是将全部的事情,在一个地方都处理完了,而工厂方法却是创建了一个框架,让子类决定要如何实现。

例如:在工厂方法中我们有一个FactoryMethod()方法提供了一般的框架,一边创建Dao,FactoryMethod()方法依赖工厂方法创建具体类,决定制造出的Dao是什么。

简单工厂的做法,可以将对象的创建封装起来,但是简单工厂不具备工厂方法的弹性,因为简单工厂不能变更正在创建的产品。

  • 这样的调整好处在于什么?

当我们需要条件一个新扩展Member数据操作类时,我们有统一的接口来,具体的操作方法都可不变,改动部分只需要扩展现有的MemberDaoFactory.cs,降低了应用层的耦合度。

  •  优缺点:

  1.) 优点:

a.) 降低了应用层次调用的耦合度;

b.) 当扩展时,有统一的接口类,开发更规范;

c.) 代码逻辑更清晰,代码更易管理维护。    

  2.) 缺点:

a.) 适用性很有限,前提条件有局限性;当我们的接口类MemberDaoBase.cs变动时,我们就需要改动多处代码;

b.) 当需要扩展时,我们依然避免不了要改动代码(尽管可以进一步改进通过设置配置和反射达到避免MemberDaoFactory变动,但是当我们需要添加新的扩展时还避免不了改动代码)。

参考资料:《Head First 设计模式》

  欢迎拍砖!请牛人们给指点。

(Factory method)工厂方法设计模式的更多相关文章

  1. Factory Method 工厂方法模式

    Factory method工厂方法模式是一种实现了“工厂”概念的面向对象设计模式.就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题.工厂方法模式的实质是“定义一个创建对象 ...

  2. 面向对象设计模式纵横谈:Factory Method 工厂方法模式(笔记记录)

    从耦合关系谈起 耦合关系直接决定着软件面对变化时的行为 -模块与模块之间的紧耦合使得软件面对变化时,相关模块都要随之更改 -模块与模块之间的松耦合使得软件面对变化时,一些模块更容易被替换或者更改,但其 ...

  3. c++ 设计模式8 (Factory Method 工厂方法)

    5. “对象创建”类模式 通过“对象创建”类模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定.它是接口抽象之后的第一步工作. 5.1 工厂方法 动机: ...

  4. 使用C# (.NET Core) 实现简单工厂(Simple Factory) 和工厂方法设计模式 (Factory Method Pattern)

    本文源自深入浅出设计模式. 只不过我是使用C#/.NET Core实现的例子. 前言 当你看见new这个关键字的时候, 就应该想到它是具体的实现. 这就是一个具体的类, 为了更灵活, 我们应该使用的是 ...

  5. Java设计模式:Factory Method(工厂方法)模式

    概念定义 工厂方法(Factory Method)模式,又称多态工厂(Polymorphic Factory)模式或虚拟构造器(Virtual Constructor)模式.工厂方法模式通过定义工厂抽 ...

  6. C#面向对象设计模式纵横谈——5.Factory Method 工厂方法模式(创建型模式)

    动机 (Motivation) 在软件系统中,经常面临着“某个对象”的创建工作; 由于需求的变化,这个对象经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何应对这种变化?如何提供一种“封装机制” ...

  7. 设计模式之 Factory Method 工厂方法

    看到的比较有意思的一篇描述工厂方法的文章. http://www.codeproject.com/Articles/492900/From-No-Factory-to-Factory-Method 总 ...

  8. 设计模式C++学习笔记之五(Factory Method工厂方法模式)

      工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中.核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的 ...

  9. Factory Method(工厂方法)-对象创建型模式

    1.意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method使一个类的实例化延迟到其子类. 2.动机 框架使用抽象类定义和维护对象之间的关系.这些对象的创建通常也由框架 ...

  10. 3.Factory Method 工厂方法模式(创建型模式)

    1.定义: 定义一个用于创建对象的接口,让子类决定实例化哪一个类.Factory Method使得一个类的实例化延迟到子类. 2.实现代码如下: /// <summary> /// 工厂方 ...

随机推荐

  1. Yii源码阅读笔记(十七)

    View.php,继承了component,用于渲染视图文件: namespace yii\base; use Yii; use yii\helpers\FileHelper; use yii\wid ...

  2. Off-heap Memory in Apache Flink and the curious JIT compiler

    https://flink.apache.org/news/2015/09/16/off-heap-memory.html   Running data-intensive code in the J ...

  3. Tomcat7 安装StartSSL证书笔记

    1.Tomcat-Native安装 使用StartSSL,Tomcat必须用apr方式启动(apr方式对于静态的内容,比默认的bio效率要高很多倍) Windows下tomcat-native安装 直 ...

  4. selenium By 元素定位详解

    转自:http://blog.sina.com.cn/s/blog_6966650401012a6u.html WebDriver拾级而上·之三 定位页面元素 selenium-webdriver提供 ...

  5. Qt设置系统时间(使用SetSystemTime API函数)

    大家都知道Qt中有QDateTime等有关时间与日期的类,类中包含很多成员函数,可以很方便的实现有关时间与日期的操作,比如:想要获得系统当前的时间与日期,可以调用currentDateTime();  ...

  6. 用户控件UserControl图片资源定位(一)---Xaml引用图片

    MEF编程实现巧妙灵活松耦合组件化编程,一些细节需要花费不小心思去处理: 其中组件中若包含用户控件,且需要访问图片资源,那么Xaml引用资源需要做以下设置 1. 用户控件(usercontrol)所在 ...

  7. POI简易帮助文档系列--给Excel设置样式

    正如Html需要CSS一样,我们的POI生成的Excel同样需要样式才能更完美的表现我们的数据.下面还是从简单的例子出发,学习和了解POI的样式设计. 一.我的位置. package com.myja ...

  8. 简易自定义下拉菜单 与简易默认下拉html片段

    简易自定义下拉选择 html片段 html: <div class="select_box province"> <div class="selecte ...

  9. 美国VPS - DigitalOcean 推荐创业团队使用

    初创公司DigitalOcean在美国正迅速成为一个家喻户晓的公司.每月5美元,该公司就可以让你享受到一个虚拟的私有服务器(或者说droplets,很多公司都这么称呼它).该公司的联合创始人兼首席执行 ...

  10. 一些html页面资料

    一下没有什么重要的,只是我平时积累的一些页面,紧急时或许会有用,相信过一段时间去东宇(公司分公司)了,这些资料页带不走,还不如留在博客里,趁组长级别们开会去了,他们已经开了一个点啦!我的组长去东宇查看 ...