小话设计模式(二)工厂方法模式
工厂方法(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;}
似乎非静态的工厂会好一点,但是仍然不可避免的要每次创建一个工厂实例。
实际情况下,似乎简单工厂运用的更广泛一些,虽然违背了开闭原则,但是写起了比较方便,适用于轻量级的继承关系。
小话设计模式(二)工厂方法模式相关推荐
- C#设计模式(3)——工厂方法模式
一.引言 在简单工厂模式中讲到简单工厂模式的缺点,有一点是--简单工厂模式系统难以扩展,一旦添加新产品就不得不修改简单工厂方法,这样就会造成简单工厂的实现逻辑过于复杂,然而本专题介绍的工厂方法模式可以 ...
- 设计模式之工厂方法模式(创建型)
一.模式定义 工厂方法模式:又称工厂模式,也叫虚拟构造器模式,属于构建型设计模式,工厂方法模式是在简单工厂模式上进行拓展,生产产品的过程由具体工厂类实现,基类只实现接口,这使得工厂方法模式可以在不修改 ...
- 设计模式:工厂方法模式(Factory method)
设计模式:工厂方法模式(Factory method) 一.问题 在前一章中通过披萨的实例介绍了简单工厂模式.在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨. ...
- python类是实例的工厂_Python设计模式之工厂方法模式实例详解
本文实例讲述了Python设计模式之工厂方法模式.分享给大家供大家参考,具体如下: 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定实例化哪一个类, ...
- 设计模式复习-工厂方法模式
设计模式复习-工厂方法模式 相对于简单工厂,工厂方法是把算法类的实例化延迟到了调用者那去做,调用者根据自己的需要,自己实例化相关的工厂并且生产相关算法.这么做是因为简单工厂是不满足OCP的,因为如果 ...
- 设计模式之工厂方法模式应用例题
设计模式之工厂方法模式应用例题 题目描述 类结构图及相关说明 程序代码 运行结果 题目描述 现需要设计一个程序来读取多种不同类型的图片格式,针对每一种图片格式都设计一个图片读取器(ImageReade ...
- 【设计模式】工厂方法模式(C#)
[设计模式]工厂方法模式 1.概述 针对简单工厂中的缺点,使用工厂方法模式就可以完美的解决,完全遵循开闭原则. 定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象.工厂方法使一个产品类的实例化 ...
- 一文叫你弄懂Java设计模式之工厂方法模式:图解+日志记录器代码实例
文章目录 详解Java设计模式之工厂方法模式 案例引入工厂方法模式 工厂方法模式 定义 案例分析 UML类图分析 代码分析 工厂方法的重载 工厂方法的隐藏 模式优点 模式缺点 模式适用环境 详解Jav ...
- Java二十三设计模式之------工厂方法模式
一.工厂方法模式(Factory Method) 工厂方法模式有三种 1.普通工厂模式:就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建.首先看下关系图: 举例如下:(我们举一个发送邮件和短 ...
- 设计模式笔记之二工厂方法模式
工厂方法模式 为什么引入工厂方法模式? 当我们需要创建多个实例的时候,而这些类又是有着公共的方法,区别就是实现的具体操作不同,我们需要专门为这些类创建实例,但是,如果我们没有创建这些的类的权限的时候, ...
最新文章
- java session 作用范围_ssm项目session使用及其作用域问题
- Cambridge Judge Business school faculty review
- 数据结构排序1-冒泡,选择,插入排序
- 万圣节头像小程序源码
- php 价格计算方法,PHP算法逻辑:如何计算购买量?
- Python使用Scrapy爬虫框架爬取天涯社区小说“大宗师”全文
- 东航期货行情接口和交易接口(20190509)
- 自然数从1到n之间,有多少个数字含有1
- BFS POJ 3278 Catch That Cow
- 证券期货信息安全等级保护测评
- JPM Coin— 货币非国家化的开端 | TokenInsight
- 论文选题、标题、摘要怎么写
- linux 下载百度网盘资源 centos安装aria2
- 视频管理系统源码php,video cms 视频分享管理系统
- 你工作经验欠缺,如何能胜任这项工作?
- 安卓开发 应用下载代码
- 用物理学分析马歇尔的价格均衡论
- C++ reverse
- uniapp提示用户开启定位,跳转到开启定位页面
- PDF怎么合并呢?speedPDF帮您免费在线合并PDF文档
热门文章
- cad标注样式快捷键_CAD标注样式如何设置?(教程篇)
- 2019MacBook Pro连结Keyboard K380的问题解决
- iOS怎么防止文件被Icloud或者iTunes备份
- Python 同时继承多个类
- ps闪电效果制作教程和PS闪电笔刷、插件下载制作闪电效果
- 怎么配置opencv才能不用每次都重新配置一遍?
- 服务器维护后黑莲花刷新,黑莲花刷新问题XLSS冬泉燃烧东瘟疫有黑莲花的点有什么刷新规律 爱问知识人...
- Puppeteer使用总结
- 激动之余 写点闲聊来记录一下
- PopStar(消灭星星)游戏源代码下载、分析及跨平台移植—第一篇(界面)