设计模式(2)工厂方法模式(Factory Method)
0 工厂方法模式简介
0.0 工厂方法模式定义
工厂方法模式是在简单工厂模式基础上,为解决更复杂的对象创建问题而衍生进化出来的一种创建型模式。
工厂方法模式的核心思想是定义一个用于创建对象的接口,让其子类去决定去实例化哪个具体类的对象,工厂方法模式可以使一个类的实例化动作延迟到其子类。
工厂方法模式结构图如下
0.1 工厂方法模式应用场景
还接着祭坛生产英雄的示例,我们已经在简单工厂模式一文中通过创建简单工厂方法类,来实现暗夜精灵种族4个英雄的创建
/// <summary>
/// 创建英雄的静态方法
/// </summary>
/// <param name="heroName">英雄名称</param>
/// <returns></returns>
public static IHero CreateHero(string heroName)
{
switch (heroName)
{
case "DH":
return new DH();
case "WD":
return new WD();
case "KOG":
return new KOG();
case "POM":
return new POM();
default:
return null;
}
}
假设现在我们要创建不死族的英雄怎么办呢,如果依然使用简单工厂方法类,则首先需要实现不死族四个英雄类。
/// <summary>
/// 死亡骑士
/// </summary>
public class DK : IHero
{
/// <summary>
/// 秀出自己的技能
/// </summary>
public void ShowSkills()
{
Console.WriteLine("我是死亡骑士,我会死亡缠绕、死亡契约、邪恶光环和操纵死尸。");
}
}
/// <summary>
/// 巫妖
/// </summary>
public class Lich : IHero
{
/// <summary>
/// 秀出自己的技能
/// </summary>
public void ShowSkills()
{
Console.WriteLine("我是巫妖,我会霜冻新星、寒冰甲、黑暗仪式和死亡凋零。");
}
}
/// <summary>
/// 地穴领主
/// </summary>
public class DL : IHero
{
/// <summary>
/// 秀出自己的技能
/// </summary>
public void ShowSkills()
{
Console.WriteLine("我是地穴领主,我会穿刺、刺盾、腐蚀甲虫和蝗群。");
}
}
/// <summary>
/// 恐惧魔王
/// </summary>
public class CL : IHero
{
/// <summary>
/// 秀出自己的技能
/// </summary>
public void ShowSkills()
{
Console.WriteLine("我是恐惧魔王,我会腐臭群蜂、睡眠、吸血光环、地狱火。");
}
}
然后需要修改工厂方法,增加switch语句中的类型,将不死族四个英雄创建逻辑添加进去。
/// <summary>
/// 创建英雄的静态方法
/// </summary>
/// <param name="heroName">英雄名称</param>
/// <returns></returns>
public static IHero CreateHero(string hero
{
switch (heroName)
{
//暗夜精灵
case "DH":
return new DH();
case "WD":
return new WD();
case "KOG":
return new KOG();
case "POM":
return new POM(); // 不死族
case "DK":
return new DK();
case "Lich":
return new Lich();
case "CL":
return new CL();
case "DL":
return new DL();
default:
return null;
}
}
还有兽族及人族,也需要如此修改。到此我们会感觉存在有以下问题
1、随着英雄的增多,简单工厂类需要反复修改。
2、简单工厂类过于庞大,职责混乱,负责了四个种族所有英雄的创建,而实际上,玩家在进入游戏时已经选好了自己的种族,只有可能创建所选种族的英雄。
我们到了这里,首先要想到的是,既然四个种族,分别有自己的祭坛,产生改种族的英雄,我们应该将简单工厂类按照种族进行职责拆分,此时参考上面提到的工厂方法模式定义以及结构图,我们会发现,现在是到了工厂方法模式出场的时候了。
1 工厂方法模式详解
1、提炼工厂方法接口
将原来的简单工厂类,进一步提炼为一个工厂方法接口,其包含一个名为CreateHero的接口。
/// <summary>
/// 工厂方法接口
/// </summary>
public interface IFactory
{ /// <summary>
/// 创建英雄的方法
/// </summary>
/// <param name="heroName">英雄名称</param>
/// <returns></returns>
IHero CreateHero(string heroName);
}
2、实现四个种族的工厂方法
四个种族创建英雄的工厂方法继承自工厂方法接口,实现CreateHero。
/// <summary>
/// 暗夜精灵种族英雄工厂类
/// </summary>
public class NEFactory : IFactory
{ /// <summary>
/// 创建英雄的静态方法
/// </summary>
/// <param name="heroName">英雄名称</param>
/// <returns></returns>
public IHero CreateHero(string heroName)
{
switch (heroName)
{
//暗夜精灵
case "DH":
return new DH();
case "WD":
return new WD();
case "KOG":
return new KOG();
case "POM":
return new POM();
default:
return null;
}
}
}
/// <summary>
/// 不死族英雄工厂类
/// </summary>
public class UDFactory : IFactory
{ /// <summary>
/// 创建英雄的静态方法
/// </summary>
/// <param name="heroName">英雄名称</param>
/// <returns></returns>
public IHero CreateHero(string heroName)
{
switch (heroName)
{ // 不死族
case "DK":
return new DK();
case "Lich":
return new Lich();
case "CL":
return new CL();
case "DL":
return new DL();
default:
return null;
}
}
}
3、客户端调用
static void Main(string[] args)
{
IFactory factory = new NEFactory(); // 初始化一个暗夜精灵族的英雄工厂
Console.WriteLine("我在开局时选择了暗夜精灵族,我的首发英雄是DH。");
IHero dh = factory.CreateHero("DH");
dh.ShowSkills(); factory = new UDFactory(); // 初始化一个不死族的英雄工厂
Console.WriteLine("我在开局时选择了不死族,我的首发英雄是DK。");
IHero dk = factory.CreateHero("DK");
dk.ShowSkills(); Console.ReadLine();
}
4、通过反射实例化具体的工厂方法类
在实际应用中跟上面不同种族创建英雄的例子类似,一般在系统启动时就已经确定要使用哪种方法实例化工厂方法类,通常我们可以将工厂类的实例化通过配置文件的方式确定,从而避免源码的修改。
string factoryName = ConfigurationManager.AppSettings["FactoryName"]; // 读取配置文件
IFactory factory = (IFactory)Assembly.Load("FactoryMethodPattern").CreateInstance("FactoryMethodPattern." + factoryName); // 实例化配置的工厂方法类
2 总结
工厂方法模式具有以下优点
1、更容易对现有功能进行扩展,如果有新的需求,只需要实现一个相应的工厂方法实现类即可,无需修改现有代码。
2、不同工厂方法类,实现了单一职责的设计原则。
工厂方法模式的缺点
由于具体的对象由具体指定的工厂方法类创建,导致具体产品和工厂方法类之间具有较强的耦合性
设计模式(2)工厂方法模式(Factory Method)的更多相关文章
- 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)
原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...
- 设计模式-03工厂方法模式(Factory Method Pattern)
插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...
- 【设计模式】工厂方法模式 Factory Method Pattern
在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...
- 二十四种设计模式:工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...
- 设计模式之工厂方法模式(Factory Method Pattern)
一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...
- 设计模式之 - 工厂方法模式 (Factory Method design pattern)
1. 模式意图: 定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...
- 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源
概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...
- 工厂方法模式-Factory Method(Java实现)
工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...
- 浅谈C++设计模式之工厂方法(Factory Method)
为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...
- IOS设计模式浅析之工厂方法模式(Factory Method)
概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对 ...
随机推荐
- 【lucene系列学习四】log4j日志文件实现多线程的测试
参考资料:http://nudtgk2000.iteye.com/blog/1716379 首先,在http://www.apache.org/dyn/closer.cgi/logging/log4j ...
- js图片轮播
html部分 <a href="" id="pta"><div id="picture" class="pt&q ...
- 安卓OKhttp请求封装
目前安卓开发中使用的网络工具为OKhttp,但是okhttp的使用还不是很方便,在okhttp的基础上再对请求进行封装会极大的方便网络调用. 下面直接上代码. 请求封装 public class Ht ...
- 对象克隆(clone)实例详解
<?php class Staff { public $name; public $age; public $salary; public function __construct($name, ...
- [笔记]ACM笔记 - 组合数
一.高中数学公式复习 , (好吧这个没学过但是既然看到了就一并抄过来了) 二.快速求组合数取模C(n, m)%p 当n和p大小不同时方法有不同. 1. n很小,p随意,p不需要为素数 1) 原理 使用 ...
- c#接口使用详解
c#接口使用详解 c#中接口隐式与显示实现 c#中接口可以隐式实现.显示实现,隐式实现更常使用.显示实现较少使用 其区别在于 显示实现避免接口函数签名冲突 显示实现只可以以接口形式调用 显示实现其子类 ...
- fopen的使用小记
整理自https://msdn.microsoft.com/zh-cn/library/t3ayayh1(VS.80).aspx errno, _doserrno, _sys_errlist, and ...
- swift学习 - collectionView
swift CollectionView学习 效果图: 源码: ContModel.swift import UIKit class ContModel: NSObject { var title:S ...
- Nginx教程(四) Location配置与ReWrite语法
Nginx教程(四) Location配置与ReWrite语法 1 Location语法规则 1.1 Location规则 语法规则: location [=|~|~*|^~] /uri/ {- } ...
- 开涛spring3(3.3) - DI 之 3.3 更多DI的知识
3.3.1 延迟初始化Bean 延迟初始化也叫做惰性初始化,指不提前初始化Bean,而是只有在真正使用时才创建及初始化Bean. 配置方式很简单只需在<bean>标签上指定 “lazy- ...