设计模式(0)简单工厂模式

设计模式(1)单例模式(Singleton)

源码地址

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)的更多相关文章

  1. 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern)

    原文:乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 工厂方法模式(Factory Method Pa ...

  2. 设计模式-03工厂方法模式(Factory Method Pattern)

    插曲.简单工厂模式(Simple Factory Pattern) 介绍工厂方法模式之前,先来做一个铺垫,了解一下简单工厂模式,它不属于 GoF 的 23 种经典设计模式,它的缺点是增加新产品时会违背 ...

  3. 【设计模式】工厂方法模式 Factory Method Pattern

    在简单工厂模式中产品的创建统一在工厂类的静态工厂方法中创建,体现了面形对象的封装性,客户程序不需要知道产品产生的细节,也体现了面向对象的单一职责原则(SRP),这样在产品很少的情况下使用起来还是很方便 ...

  4. 二十四种设计模式:工厂方法模式(Factory Method Pattern)

    工厂方法模式(Factory Method Pattern) 介绍定义一个用于创建对象的接口,让子类决定将哪一个类实例化.Factory Method使一个类的实例化延迟到其子类. 示例有SqlMes ...

  5. 设计模式之工厂方法模式(Factory Method Pattern)

    一.工厂方法模式的诞生 在读这篇文章之前,我先推荐大家读<设计模式之简单工厂模式(Simple Factory Pattern)>这篇文档.工厂方法模式是针对简单工厂模式中违反开闭原则的不 ...

  6. 设计模式之 - 工厂方法模式 (Factory Method design pattern)

    1. 模式意图:  定义一个用于创建对象的接口,让子类决定实例化哪一个类,工厂方法使一个类的实例化延迟到其子类. 2. 别名(Virtual Constructor) 3. 结构 4. 工厂方法模式C ...

  7. 【UE4 设计模式】工厂方法模式 Factory Method Pattern 及自定义创建资源

    概述 描述 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式,或者多态工厂(Polymorphic Factory)模式 工厂父类负责定义创建产品对象的公共接口,而工厂子类 ...

  8. 工厂方法模式-Factory Method(Java实现)

    工厂方法模式-Factory Method 工厂方法模式定义一个用于创建对象的接口,让子类决定实例化哪一个类.工厂方法让实例化的具体内容交给子类工厂来进行. 本文中的例子是这样的. 生产一个身份证, ...

  9. 浅谈C++设计模式之工厂方法(Factory Method)

    为什么要用设计模式?根本原因是为了代码复用,增加可维护性. 面向对象设计坚持的原则:开闭原则(Open Closed Principle,OCP).里氏代换原则(Liskov Substitution ...

  10. IOS设计模式浅析之工厂方法模式(Factory Method)

    概述 在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的具体实现经常面临着剧烈的变化,但是它却拥有比较稳定的接口. 如何隔离出这个易变对象的变化,使得系统中“其它依赖该对象的对 ...

随机推荐

  1. 与64位版本的Windows不兼容,masm运行不了

    问题: 在Window64位运行不了的masm 解决方法: 1.下载DosBox0.74(当前最新): 2.安装后运行,运行后出现控制台: 3.在DosBox的控制台下运行 Mount x: x:/m ...

  2. 基于Struts2的SpringMVC入门

    1.SpringMVC概述 (1)SpringMVC为表现层提供基础的基于MVC设计理念的优秀Web框架, (2)SpringMVC通过一套mvc的注解,让POJO成为处理请求的控制器,而无需任何接口 ...

  3. ubuntu系统搭建以太坊私有链

    1.安装curl.git apt-get update apt-get install git apt-get install curl 2.安装go curl -O https://storage. ...

  4. 前端魔法堂:onsubmit和submit事件处理函数怎么不生效呢?

    前言  最近在用Polymer增强form,使其支持表单的异步提交,但发现明明订阅了onsubmit和submit事件,却怎么也触发不了.下面我们将一一道来. 提交表单的方式 表单仅含一个以下的元素时 ...

  5. C语言模拟实现多态

    一.多态的主要特点 1.继承体系下.继承:是面向对象最显著的一个特性.继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性 和行为,并能扩展新的能力,已有类被称为父类/基类,新增加的类被称作子 ...

  6. SQL优化一

    1.行列转换: decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值); select decode(sign(变量1-变量2),-1,变量1,变量2) from dual ...

  7. html学习笔记 - 特殊字符

  8. 第 7 章 MySQL 数据库锁定机制

      前言: 为了保证数据的一致完整性,任何一个数据库都存在锁定机制.锁定机制的优劣直接应想到一个数据库系统的并发处理能力和性能,所以锁定机制的实现也就成为了各种数据库的核心技术之一.本章将对 MySQ ...

  9. Metrics

    系统开发到一定的阶段,线上的机器越来越多,就需要一些监控了,除了服务器的监控,业务方面也需要一些监控服务.Metrics作为一款监控指标的度量类库,提供了许多工具帮助开发者来完成自定义的监控工作. 举 ...

  10. superagent和request结果转换区别

    superagent和request结果转换区别 使用superagent和request抓取页面内容时,两个抓取内容都可以被cheerio进行处理.但处理时有个细微差别. 1. 使用superage ...