西西软件下载最安全的下载网站、值得信赖的软件下载站!

首页编程开发其它知识 → 设计模式之工厂模式与抽象工厂模式

设计模式之工厂模式与抽象工厂模式

相关软件相关文章发表评论 来源:西西整理时间:2012/12/5 17:38:48字体大小:A-A+

作者:西西点击:21次评论:0次标签: 设计模式

QQ音乐2016V12.57.3804.412 官方正式版
  • 类型:音频播放大小:21.5M语言:中文 评分:9.2
  • 标签:
立即下载

刚接触设计模式的第一课,工厂模式与抽象工厂,确实感觉到了设计模式的抽象与强大作用力,学习过程中自己动手设计了一个小游戏的角色。

假定一个游戏中有很多怪物角色,如蜘蛛,马,猴子,等,此游戏有多种游戏级别,先假定为3级。

设计游戏时必须考虑到:

1,游戏的角色可扩展性

2,游戏易于维护(如,游戏中怪物角色易于管理)

暂时不考虑其他的问题,先说说角色的设计问题。

游戏中有很多怪物角色,也分为三级,即怪物也有三个级别,那么,怎么设计角色的继承体系呢?

至少有以下两种策略:

a),游戏维护一个怪物超类,所有怪物直接继承,将这些子类再作为超类,供“三个级别”怪物类继承,类结构大致为:

CMonster

CHouse :public CMonster,......

CHighLevelHouse :public CHouse,CLowLevelHouse :public CHouse.....

b),游戏维护一个怪物超类,让三个级别继承此超类,再分别让每个怪物继承之,类结构大致为:

CMonster

CHighLevelMonster : public CMonster,CLowLevelMonster : public CMonster.......

CHighLevelHouse : public CHighLevelMonster,CLowLevelHouse: public CLowLevelMonster....

暂且不论这两种继承方案怎样,下面就这两种方案分别使用工厂模式和抽象工厂得到怪物对象。

一,使用工厂模式

使用工厂模式的目的在于代码的客户不需要亲自实例化一个对象,客户只需要操心:“我要得到什么”,而不用操心:“我要使用哪一个具体的类去获得”;考虑在可预见的将来客户需要的对象改变了,那么,他是否不得不去更改那一段new Chouse()的代码?但如果使用工厂方法,替代这种“硬编码”,或言之“过程性编码”,则他不需要更改任何代码,而只需要更改工厂里生产此对象的方法,将生产的对象替换一下就能做到。这是很具有优越性的,假定程序中出现了一万次new Chouse(),后来我们不再需要Chouse这个对象,而是需要重写或者有较Chouse有大更改的ChouseChanged 类实例,这就意味着一天悲惨的查找->替换工作的开始!但如果使用了工厂方法,以一种封闭的方法产生客户需要的对象,就只需要在工厂内部修改生成的方法,替换一次即可!

以上是使用的目的!但如何使用呢,下面就来深入的了解工厂模式。工厂从某种角度上就是一种透明的机器,这种机器有很多型号,有的能生产猴子对象,有的能生成蜘蛛对象,等等。那么,为什么不是“一部透明的机器”呢,因为它要生产很多种对象,“一部机器”是不能生产末知种类,末知数量的对象的。那,为什么不将某参数传入此机器,让它能根据参数生产特定的对象呢?答案在于,可扩展性。如前所言,工厂并不知道它要生产怎样的对象,生产多少种类型的对象,如果单纯地以参数去界定,若以后再增加了一/多种对象,则还需要修改工厂的生产方法,可能是增加switch里面的case语句,这样就涉及到维护问题了,一旦忘记,则导致新加的对象创建不成功!记住,工厂本应是一个抽象的概念,不是一个具体的概念。所以生产多种对象,必须有多种具体的工厂!如,生产猴子的猴子工厂,生产蜘蛛的蜘蛛工厂,等。这就是工厂模式。

二,使用抽象工厂模式

再来说说抽象工厂模式,其实本人觉得抽象工厂模式也就是工厂模式,只是它是前一种模式复杂一些的模式,但本质还是一样的,如果你会用工厂模式,那么你一定会用抽象工厂模式!

已经知道了为什么要使用工厂模式,现在让我们开始分析在那个游戏中,怎样通过工厂模式去获得怪物。

现在的情况稍微复杂了一些,增加了游戏的难易级别,则不能简单的直接使用工厂模式,因为无法满足三个级别的限制,那么,抽象工厂便出现了,其实质是将工厂再次向上抽象,产生继承得到多个抽象的工厂。

考虑将工厂归类,则至少有以下两种策略:

a),定义三个“级别工厂”:高级怪物工厂,中级怪物工厂,低级怪物工厂,让每个工厂去生产所有类型的怪物

b),定义多个“怪物工厂”:猴子工厂,蜘蛛工厂,马工厂,让每个工厂去生产三种怪物(高级,中级,低级)

首先,我们先决策哪一种策略更优,把“更优”换一种说法,即是文章最开始说到的两个条件:可扩展性,可维护性。先考察可扩展性:假设游戏以后增加了几十种,几百种,新的怪物,则b中的怪物工厂则飙增到相同的数目,相比之下 a 中的工厂数目则不会增加。但 a 也会付出惨重的代价:每个工厂里面,增加几十个,几百个生产对象的方法。有一个经验,“集中地增加代码,而不是分散地增加或者修改既有代码”往往表现出更优的可扩展性。显然,定义怪物工厂可获得更好的可扩展性。因为在b中,新增加一种怪物,只需要增加一个工厂,同时在里面写入三个方法分别产生三种级别的怪物即可,相比a中的在三个工厂中都增加一个方法(不能遗忘),显然更优一些!但b也不是最优解,因为如果游戏级别一旦增加,则需要在每个怪物工厂中去增加相应的代码,而a中则只需要再新增加一个工厂,并将其它工厂里的代码直接拷到下面即可工作。但我们之前有约定:怪物的易变性大于级别的易变性,毕竟,一个游戏的游戏级别是不会常变的,这也符合假定!如果要彻底解决这个问题,我们得时刻记住一句话:“永远要对变化的东西抽象(封装)”。于是,我们自然会想到,使用继承去获得游戏级别变化下的可扩展性,我们可以在b的基础上再使用一层抽象,让怪物工厂里的生产怪物的方法是抽象的,(C++里使用vitual修饰),让每个怪物工厂被三个类(目前是三个级别)去继承,可能是这样的类结构:

CFactory

CHouseFactory : public CFactory,CMonkeyFactory : public CFactrory,.......

CHighLevelFactory : public CHosueFactory,CLowLevelFactory : public CHouseFactory....

这样会获得完全的扩展性,但与之相应的代价是子类膨胀问题,子类巨多!每个怪物工厂类有三个子类!

这里可以做权衡,减少可扩展性,增加新函数代替子类:可能的结构如下:

CFactory

{

 virtual CHighLevelMonster* getHighLevelMonster();

   virtual CMiddleLevelMonster* getMiddleLevelMonster();

   virtual CLowLevelMonster* getLowLevelMonster();

 //可能只有这三种级别

}

CHouseFactory : public CFactory

{

 CHighLevelMonster* getHighLevelMonster();

   CMiddleLevelMonster* getMiddleLevelMonster();

   CLowLevelMonster* getLowLevelMonster();

}

说明:

1,在超类工厂CFactory中任何获得对象的方法都是virtual的

2,抽象工厂中的获得对象的方法的返回值类型必定不同!(第一个是CHighLevelMonster*,第二个是CMiddleLevelMonster*,第三个是CLowLevelMonster*)。谨记:如果它们的返回值一样,则退化为了工厂模式,而不是抽象工厂模式!之所以叫抽象工厂,是因为抽象工厂一旦实例化,则可以实例化为多种类型的工厂,每一种工厂用来生产相关,但不同类型的对象,各种实例化出来的工厂之间的差别在于,它们生产这些对象的方式或者结果不同!游戏需要三种级别的怪物,则每个工厂按自己的方式去生成它们,(“不同的方式”体现在,每个工厂生产出的怪物(即使级别相同,但)不同)

三,反过来再谈继承方案

在文章的最开始,我们提出了两种继承策略,

a),游戏维护一个怪物超类,所有怪物直接继承,将这些子类再作为超类,供“三个级别”怪物类继承,类结构大致为:

CMonster

CHouse :public CMonster,......

CHighLevelHouse :public CHouse,CLowLevelHouse :public CHouse.....

b),游戏维护一个怪物超类,让三个级别继承此超类,再分别让每个怪物继承之,类结构大致为:

CMonster

CHighLevelMonster : public CMonster,CLowLevelMonster : public CMonster.......

CHighLevelHouse : public CHighLevelMonster,CLowLevelHouse: public CLowLevelMonster....

我们前面使用的抽象工厂模式正是基于的第二种继承方案,所以被抽象的工厂是“怪物工厂”,而不是“级别工厂”,然后在各个工厂里生产出的是不同级别的怪物。若我们使用第一种继承方案,由正好对应了将工厂归类中的 a) ,定义三个“级别工厂”:高级怪物工厂,中级怪物工厂,低级怪物工厂,让每个工厂去生产所有类型的怪物此时,形成的是“级别工厂”,在每个级别工厂里,生产出的是级别相同但属性不同的怪物,可能的代码是这样的:

CFactory

{

 virtual CMonkey* getMonkey();

   virtual CHouse* getHouse();

   virtual CSpiter* getSpiter();

  .............//省略掉其它怪物

}

CHighLevelFactory : public CFactory

{

   CMonkey* getMonkey();

   CHouse* getHouse();

   CSpiter* getSpiter();

   ....................

}

根据之前的讨论,b)方法的抽象工厂模式较好,所以继承方案应该是后一种要好一些

四,结语

经过之前的分析,对工厂模式和抽象工厂模式有了一定的认识,可能还存在不足之处,望读者指出,一同探讨!

    无损音乐播放器
    (18)无损音乐播放器
    现在的人们对音乐的质量越来越高,不是无损的音乐根本都听不进去,什么是无损音乐呢常见到的被称为有损压缩,有损压缩顾名思义就是降低音频采样频率与比特率,输出的音频文件会比原文件小。另一种音频压缩被称为无损压缩,能够在保存原文件的所有数据的前提下,将音频文件的体积压缩的更小,而将压缩后的音频文件还原后,能够实现与源文件相同的大小相同的码率。无损压缩格式有,而常见的主流的无损压缩格式目前有。西西小编给大家...更多>>
    mp3播放器
    (9)mp3播放器
    大多数网友上网都会听歌,有的网友对音质要求非常高,到底哪款播放器好呢目前就西西小编对市场上的播放器来看,数百度音乐播放器的音质是最好的了,无论是高品质还是无损的都非常不错。现在的主流音乐播放器都支持格式,音乐酷我音乐酷狗等都支持大部分音频格式,所以好用的播放器有很多,小编在此推荐给大家的全是播放器下载排行榜里的好播放器,希望大家喜欢。...更多>>
    音乐下载软件
    (21)音乐下载软件
    西西软件园提供好用的音乐下载软件,喜欢听歌的朋友很多,那么有什么好用的软件提供音乐下载呢西西小编就推荐几款给大家使用,有常见的播放器音乐下载工具,还有给发烧友准备的无损音乐下载工具哦。操作都很简单,常见的播放器音乐下载大家应该都很清楚,无损音乐则需要大家搜索下载,麻烦了一点而已。...更多>>
    qq音乐2015
    (17)qq音乐2015
    不是每天都会有独家音乐推荐,但是每天都可以在这里知道哪些歌曲最好听音乐,音乐你的生活。音乐官方介绍音乐是中国最大的网络音乐平台,是中国互联网领域领先的正版数字音乐服务提供商,始终走在音乐潮流最前端,向广大用户提供方便流畅的在线音乐和丰富多彩的音乐社区服务。音乐音乐是腾讯公司推出的跨平台多终端的免费音乐服务,为您提供海量乐库在线试听卡拉歌词在线首发列表漫游音乐分享等丰富多彩的音乐社区服务绿钻贵族还可...更多>>
    音乐播放器排行榜
    (19)音乐播放器排行榜
    电脑音乐播放器国内用户使用最多的应该就是酷狗音乐了,这款播放器在国内算是当家花旦,另外千千静听曾经在上可是占有很大一席的,现在改名为百度音乐喜欢千千静听的朋友可以选择百度音乐,酷我音乐盒是后起之秀不过却是长江后浪推前浪用户积累量逐日升高,另外还有些国外的播放器例如本页面都有提供下载。西西为大家精选出了音悦台酷我音乐盒酷狗音乐等诸多热门的电脑音乐播放器下载。...更多>>

    相关评论

    阅读本文后您有什么感想? 已有人给出评价!

    • 8 喜欢喜欢
    • 3 顶
    • 1 难过难过
    • 5 囧
    • 3 围观围观
    • 2 无聊无聊

    热门评论

    最新评论

    发表评论 查看所有评论(0)

    昵称:
    表情: 高兴 可 汗 我不要 害羞 好 下下下 送花 屎 亲亲
    字数: 0/500 (您的评论需要经过审核才能显示)
    推荐文章

    没有数据