工厂方法(Factory Method)由名虚构造器(Virtual Constructor),是一种创建型的设计模式。使用工厂模式的意图便是定义一个用于创建对象的接口,让子类决定实例化哪一个类。它使得一个类的实例化延迟到其子类。

考虑这种情况,游戏中背包可以存放道具(Item)和装备(Equipment),道具可使用可堆叠不可装备,装备可装备不可使用不可堆叠。他们都继承自物品(Stuff)。定义如下:

public enum StuffType
{Item,Equipment,Material,
}public abstract class Stuff
{public int id;public readonly StuffType type;public Stuff(StuffType stuffType, int stuffId){type = stuffType;id = stuffId;}
}public class Item : Stuff
{public Item(int stuffId):base(StuffType.Item, stuffId){}
}public class Equipment : Stuff
{public Equipment(int stuffId):base(StuffType.Equipment, stuffId){}
}

当我们需要根据类型创建装备或者道具的时候(例如掉落时)应该怎么办呢?你可能想到了简单工厂:

public static class StuffFactory
{public static Stuff CreateStuff(StuffType stuffType, int stuffId){Stuff stuff = null;switch (stuffType) {case StuffType.Item:stuff = new Item (stuffId);break;case StuffType.Equipment:stuff = new Equipment (stuffId);break;}return stuff;}
}

使用:

     Stuff st = StuffFactory.CreateStuff (StuffType.Equipment, 10);

恩,这样还不错。这个时候策划微笑着想你走来,你一看不妙想赶紧请假走人,策划一把抢过你的请假单,对你说“有个需求很简单,我需要增加一个材料类型,不能使用可以堆叠,可以用来合成道具或者装备”。你拿出了策划发誓不增加物品类型的录音,然而并没有什么卵用。

我们需要增加一个类,并且需要修改StuffFactory,这可能并不是你想要的,因为这违背了开闭原则(对扩展开放,对修改关闭)。所以可以考虑使用下面的方法:

public interface IFactory
{Stuff CreateStuff(int stuffId);
}public class ItemFactory:IFactory
{public Stuff CreateStuff(int stuffId){return new Item (stuffId);}
}public class EquipmentFactory:IFactory
{public Stuff CreateStuff(int stuffId){return new Equipment (stuffId);}
}

使用:

     IFactory stuffFactory = null;StuffType stype = StuffType.Item;//TODO:switch (stype) {case StuffType.Item:stuffFactory = new ItemFactory ();break;case StuffType.Equipment:stuffFactory = new EquipmentFactory ();break;}Stuff stuff = stuffFactory.CreateStuff (9);

这就是工厂方法模式。它将类型的判定交给了用户来判断,没需要增加一个类型,原有的工厂不需要做修改,而用户则需要增加一个case选项。

当我们需要增加一个材料类型时,需要为StuffType这个枚举类型添加一个项Material,并增加这些代码:

public class Material:Stuff
{public Material(int stuffId):base(StuffType.Material, stuffId){}
}public class MaterialFactory:IFactory
{public Stuff CreateStuff(int stuffId){return new Material (stuffId);}
}

工厂方法模式虽然遵守了开闭原则,但是缺点也很明显,需要为每一个类创建一个工厂类,而且为了保证多态,我们没办法将工厂类设置为静态类。

或者我们可以考虑使用泛型来解决问题:

public class TFactory<T> : IFactory where T: Stuff,new()
{public Stuff CreateStuff(int stuffId){T ret = new T ();ret.id = stuffId;return ret;}
}

我们需要为每一个类添加默认构造函数,例如:

 public Item():base(StuffType.Item, 0){}

使用:

     IFactory sf = null;StuffType tstype = StuffType.Equipment;//TODO:switch (tstype) {case StuffType.Item:sf = new TFactory<Item> ();break;case StuffType.Equipment:sf = new TFactory<Equipment> ();break;case StuffType.Material:sf = new TFactory<Material> ();break;}Stuff tstuff = sf.CreateStuff (8);

或者使用静态类:

public static class TStaticFactory
{public static T CreateStuff<T>(int stuffId) where T: Stuff,new(){T ret = new T ();ret.id = stuffId;return ret;}
}

使用:

     StuffType tsstype = StuffType.Item;Stuff tsstuff = null;int id = 7;//TODO:switch (tsstype) {case StuffType.Item:tsstuff = TStaticFactory.CreateStuff<Item> (id);break;case StuffType.Equipment:tsstuff = TStaticFactory.CreateStuff<Equipment> (id);break;case StuffType.Material:tsstuff = TStaticFactory.CreateStuff<Material> (id);break;}

似乎非静态的工厂会好一点,但是仍然不可避免的要每次创建一个工厂实例。

实际情况下,似乎简单工厂运用的更广泛一些,虽然违背了开闭原则,但是写起了比较方便,适用于轻量级的继承关系。

小话设计模式(二)工厂方法模式相关推荐

  1. C#设计模式(3)——工厂方法模式

    一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是--简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...

  2. 设计模式之工厂方法模式(创建型)

    一.模式定义 工厂方法模式:又称工厂模式,也叫虚拟构造器模式,属于构建型设计模式,工厂方法模式是在简单工厂模式上进行拓展,生产产品的过程由具体工厂类实现,基类只实现接口,这使得工厂方法模式可以在不修改 ...

  3. 设计模式:工厂方法模式(Factory method)

    设计模式:工厂方法模式(Factory method) 一.问题 在前一章中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨. ...

  4. python类是实例的工厂_Python设计模式之工厂方法模式实例详解

    本文实例讲述了Python设计模式之工厂方法模式.分享给大家供大家参考,具体如下: 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类, ...

  5. 设计模式复习-工厂方法模式

     设计模式复习-工厂方法模式 相对于简单工厂,工厂方法是把算法类的实例化延迟到了调用者那去做,调用者根据自己的需要,自己实例化相关的工厂并且生产相关算法.这么做是因为简单工厂是不满足OCP的,因为如果 ...

  6. 设计模式之工厂方法模式应用例题

    设计模式之工厂方法模式应用例题 题目描述 类结构图及相关说明 程序代码 运行结果 题目描述 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReade ...

  7. 【设计模式】工厂方法模式(C#)

    [设计模式]工厂方法模式 1.概述 针对简单工厂中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则. 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象.工厂方法使一个产品类的实例化 ...

  8. 一文叫你弄懂Java设计模式之工厂方法模式:图解+日志记录器代码实例

    文章目录 详解Java设计模式之工厂方法模式 案例引入工厂方法模式 工厂方法模式 定义 案例分析 UML类图分析 代码分析 工厂方法的重载 工厂方法的隐藏 模式优点 模式缺点 模式适用环境 详解Jav ...

  9. Java二十三设计模式之------工厂方法模式

    一.工厂方法模式(Factory Method) 工厂方法模式有三种 1.普通工厂模式:就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.首先看下关系图: 举例如下:(我们举一个发送邮件和短 ...

  10. 设计模式笔记之二工厂方法模式

    工厂方法模式 为什么引入工厂方法模式? 当我们需要创建多个实例的时候,而这些类又是有着公共的方法,区别就是实现的具体操作不同,我们需要专门为这些类创建实例,但是,如果我们没有创建这些的类的权限的时候, ...

最新文章

  1. java session 作用范围_ssm项目session使用及其作用域问题
  2. Cambridge Judge Business school faculty review
  3. 数据结构排序1-冒泡,选择,插入排序
  4. 万圣节头像小程序源码
  5. php 价格计算方法,PHP算法逻辑:如何计算购买量?
  6. Python使用Scrapy爬虫框架爬取天涯社区小说“大宗师”全文
  7. 东航期货行情接口和交易接口(20190509)
  8. 自然数从1到n之间,有多少个数字含有1
  9. BFS POJ 3278 Catch That Cow
  10. 证券期货信息安全等级保护测评
  11. JPM Coin— 货币非国家化的开端 | TokenInsight
  12. 论文选题、标题、摘要怎么写
  13. linux 下载百度网盘资源 centos安装aria2
  14. 视频管理系统源码php,video cms 视频分享管理系统
  15. 你工作经验欠缺,如何能胜任这项工作?
  16. 安卓开发 应用下载代码
  17. 用物理学分析马歇尔的价格均衡论
  18. C++ reverse
  19. uniapp提示用户开启定位,跳转到开启定位页面
  20. PDF怎么合并呢?speedPDF帮您免费在线合并PDF文档

热门文章

  1. cad标注样式快捷键_CAD标注样式如何设置?(教程篇)
  2. 2019MacBook Pro连结Keyboard K380的问题解决
  3. iOS怎么防止文件被Icloud或者iTunes备份
  4. Python 同时继承多个类
  5. ps闪电效果制作教程和PS闪电笔刷、插件下载制作闪电效果
  6. 怎么配置opencv才能不用每次都重新配置一遍?
  7. 服务器维护后黑莲花刷新,黑莲花刷新问题XLSS冬泉燃烧东瘟疫有黑莲花的点有什么刷新规律 爱问知识人...
  8. Puppeteer使用总结
  9. 激动之余 写点闲聊来记录一下
  10. PopStar(消灭星星)游戏源代码下载、分析及跨平台移植—第一篇(界面)