为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

工厂设计模式

2017-09-01 13页 doc 118KB 20阅读

用户头像

is_751406

暂无简介

举报
工厂设计模式工厂设计模式 近一年来,我写代码是失败的,没扩展性,每新增一个模块就得改动很多,if else语句或者配置文件成堆,万一if else和配置文件不管用了,就往数据库中加字段,这样的代码会让人吐血的。所以说,我一直是苦逼青年,机械地写着很戳的代码。近段时间,我好好地用Rational Rose分析了一下设计模式中的工厂模式,以此了结之前的开发模式。 工厂模式分为三种 1. 简单工厂模式(不推荐) 2. 工厂方法模式(推荐) 3. 抽象工厂模式(推荐) 先说下简单工厂模式吧,我们往往看到的就是一个BeanFactory...
工厂设计模式
工厂设计模式 近一年来,我写代码是失败的,没扩展性,每新增一个模块就得改动很多,if else语句或者配置文件成堆,万一if else和配置文件不管用了,就往数据库中加字段,这样的代码会让人吐血的。所以说,我一直是苦逼青年,机械地写着很戳的代码。近段时间,我好好地用Rational Rose了一下设计模式中的工厂模式,以此了结之前的开发模式。 工厂模式分为三种 1. 简单工厂模式(不推荐) 2. 工厂方法模式(推荐) 3. 抽象工厂模式(推荐) 先说下简单工厂模式吧,我们往往看到的就是一个BeanFactory,然后里面有个static 方法,这种模式,很常见,面试都会考,因为它体现出了java的基本特征:封装。但 是,你要看到static这个关键字, static是静态的意思,也就是说是静态绑定,子类 无法继承这个方法,那怎么扩展啊,你不可能换BeanFactoy吧,只能修改static方 法。所以违反了java的另外特征:多态和继承。我上网查了下,真正违反的是OCP 设计原则(开闭原则:对扩展是开放的,对修改是关闭的)。 简单工厂设计模式 再看工厂方法模式 工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。 工厂方法设计模式,避免了Beanfactory违法OCP设计原则。 优点:通过扩展增加BeanFactory的能力,客户依赖的是工厂,而不是依赖于某种具体事项,可以有不同的dao。 缺点:客户端依赖于一个具体的工厂实现,而且客户端每多一个需求,就要创建一个新的具体工厂类 工厂方法设计模式 抽象工厂设计模式 抽象工厂是应对产品族概念的。比如说,每个汽车公司可能要同时生产轿车,货车,客车,那么每一个工厂都要有创建轿车,货车和客车的方法。 应对产品族概念而生,增加新的产品线很容易,但是无法增加新的产品。 简单工厂模式及实例 前言 工大有许多同学是做java的,大家都知道java最大的优点是它的完全OO化和它在多年的发展过程中吸收和总结了许多先进的框架与模式,其中工厂模式就是最常用的模式之一。下面我想将我在学习和实践过程中对工厂模式的认识与了解介绍给大家。由于笔者能力限制,在实践中也没参与过什么大的项目,笔者参与过的项目用到的工厂模式主要是简单工厂模式(Simple Factory)和工厂方法模式(Factory Method),所以笔者在本文主要介绍的是这两种模式。 准备知识 在OO设计领域,我们知道前人总结了不少的经验,许多的经验在现代软件工程过程中已经被认为是原则来遵守。下面笔者摘抄几项下文涉及到的OO原则的定义。 OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭。我的理解是,对于一个已有的软件,如果需要扩展,应当在不需修改已有代码的基础上进行。 DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程。我的理解是,对于不同层次的编程,高层次暴露给低层次的应当只是接口,而不是它的具体类。 LoD(迪米特法则,Law of Demeter):只与你直接的朋友通信,而避免和陌生人通信。众所周知类(或模块)之间的通信越少,耦合度就越低,从而更有利于我们对软件的宏观管理。老子论“圣人之治”有相同的思想,《老子》云:“是以圣人之治,虚其心,实其腹,弱其志,常使民无知无欲。”,又云:“小国寡民,邻国相望,鸡犬之声相闻,民至老死,不相往来。”。佩服我们 的老祖宗,N千年前就想到了西方N千年后才想到的东西,同时也佩服《java与模式》的作者阎宏,可以用中国传统哲学思想这么生动的说明这一软件设计原则。 简单工厂模式及实例 简单工厂模式又叫静态工厂模式,顾名思义,它是用来实例化目标类的静态类。下面我主要通过一个简单的实例说明简单工厂及其优点。 比如有个国家的运动员协会,他们是负责登记与注册职业运动员的(就好像我们国家的体育总局,呵呵,无论足球篮球还是乒乓球的运动员都必须在这里注册才能拿到我们国家职业运动员牌照)。一家体育俱乐部(比如篮球的广东宏远,足球的深圳健力宝)想获得球员为自己俱乐部效力,就必须通过这个运动员协会。 根据DIP我们可以设计一个“运动员”接口,“足球运动员”和“篮球运动员”(还有其他运动员)都实现“运动员”这个接口。而“运动员协会”就是一个简单工厂类,它负责实例化“运动员”。我们这里的“俱乐部”就是一个客户端(Client),不同的“俱乐部”就是不同的客户端。具体如下图表示: 对于不同的俱乐部对象(无论是八一还是深圳健力宝),他们都是面向“运动员”接口编程,而不用管是“足球运动员”还是“篮球运动员”,也就是说实现了“运动员”接口的具体类“足球运动员”无需暴露给客户端。这也满足了DIP。但具体的俱乐部(比如足球的深圳健力宝)如何确保自己获取的是自己想要的运动员(健力宝俱乐部需要的当然是足球运动员)呢,这就需要“运动员协会”这一工厂类了。俱乐部通过调用“运动员协会”的具体方法,返回不同的实例。这同时也满足了LoD,也就是“深圳健力宝足球俱乐部”对象不直接与“足球运动员:李毅”对象通信,而是通过他们共同的“朋友”——“国家体育总局”通信。 下面给出各个类的程序,会有助于读者更好的了解笔者之前的介绍。 Code: [Copy to clipboard] 运动员.java public interface 运动员 { public void 跑(); public void 跳(); } 足球运动员.java public class 足球运动员 implements 运动员 { public void 跑(){ //跑啊跑 } public void 跳(){ //跳啊跳 } } 篮球运动员.java public class 篮球运动员 implements 运动员 { public void 跑(){ //do nothing } public void 跳(){ //do nothing } } 体育协会.java public class 体育协会 { public static 运动员 注册足球运动员(){ return new 足球运动员(); } public static 运动员 注册篮球运动员(){ return new 篮球运动员(); } } 俱乐部.java public class 俱乐部 { private 运动员 守门员; private 运动员 后卫; private 运动员 前锋; public void test() { this.前锋 = 体育协会.注册足球运动员(); this.后卫 = 体育协会.注册足球运动员(); this.守门员 = 体育协会.注册足球运动员(); 守门员.跑(); 后卫.跳(); } } 以上就是简单工厂模式的一个简单实例,读者应该想象不用接口不用工厂而把具体类暴露给客户端的那种混乱情形吧(就好像没了体育总局,各个俱乐部在市场上自己胡乱的寻找仔细需要的运动员),简单工厂就解决了这种混乱。 我们用OCP看看简单工厂,会发现如果要对系统进行扩展的话治需要增加实现产品接口的产品类(上例表现为“足球运动员”,“篮球运动员”类,比如要增加个“乒乓球运动员”类),而无需对原有的产品类进行修改。这咋一看好像满足OCP,但是实际上还是需要修改代码的——对,就是修改工厂类。上例中如果增加“乒乓球运动员”产品类,就必须相应的修改“体育协会”工厂类,增加个“注册乒乓球运动员”方法。所以可以看出,简单工厂模式是不满足OCP的。 工厂方法模式及其实例 谈了简单工厂模式,下面继续谈谈工厂方法模式。前一节的最末点明了简单工厂模式最大的缺点——不完全满足OCP。为了解决这一缺点,设计师们提出了工厂方法模式。工厂方法模式和简单工厂模式最大的不同在于,简单工厂模式只有一个(对于一个项目或者一个独立模块而言)工厂类,而工厂方法模式有一组实现了相同接口的工厂类。下面我们通过修改上一节的实例来介绍工厂方法模式。 我们在不改变产品类(“足球运动员”类和“篮球运动员”类)的情况下,修改下工厂类的结构,如下图所示: 相关代码如下: Code: [Copy to clipboard] 运动员.java public interface 运动员 { public void 跑(); public void 跳(); } 足球运动员.java public class 足球运动员 implements 运动员 { public void 跑(){ //跑啊跑 } public void 跳(){ //跳啊跳 } } 篮球运动员.java public class 篮球运动员 implements 运动员 { public void 跑(){ //do nothing } public void 跳(){ //do nothing } } 体育协会.java public interface 体育协会 { public 运动员 注册(); } 足球协会.java public class 足球协会 implements 体育协会 { public 运动员 注册(){ return new 足球运动员(); } } 篮球协会.java public class 篮球协会 implements 体育协会 { public 运动员 注册(){ return new 篮球运动员(); } } 俱乐部.java public class 俱乐部 { private 运动员 守门员; private 运动员 后卫; private 运动员 前锋; public void test() { 体育协会 中国足协 = new 足球协会(); this.前锋 = 中国足协.注册(); this.后卫 = 中国足协.注册(); 守门员.跑(); 后卫.跳(); } } 很明显可以看到,“体育协会”工厂类变成了“体育协会”接口,而实现此接口的分别是“足球协会”“篮球协会”等等具体的工厂类。 这样做有什么好处呢,很明显,这样做就完全OCP了。如果需要再加入(或扩展)产品类(比如加多个“乒乓球运动员”)的话就不再需要修改工厂类了,而只需相应的再添加一个实现了工厂接口(“体育协会”接口)的具体工厂类。 简单工厂模式与工厂方法模式大PK 从以上对两种模式的介绍可以了解到,工厂方法模式是为了克服简单工厂模式的缺点(主要是为了满足OCP)而设计出来的。但是,工厂方法模式就一定比简单工厂模式好呢,笔者的答案是不一定。下面笔者将详细比较两种模式。 1. 结构复杂度 从这个角度比较,显然简单工厂模式要占优。简单工厂模式只需一个工厂类,而工厂方法模式的工厂类随着产品类个数增加而增加,这无疑会使类的个数越来越多,从而增加了结构的复杂程度。 2.代码复杂度 代码复杂度和结构复杂度是一对矛盾,既然简单工厂模式在结构方面相对简洁,那么它在代码方面肯定是比工厂方法模式复杂的了。简单工厂模式的工厂类随着产品类的增加需要增加很多方法(或代码),而工厂方法模式每个具体工厂类只完成单一任务,代码简洁。 3.客户端编程难度 工厂方法模式虽然在工厂类结构中引入了接口从而满足了OCP,但是在客户端编码中需要对工厂类进行实例化。而简单工厂模式的工厂类是个静态类,在客户端无需实例化,这无疑是个吸引人的优点。 4.管理上的难度 这是个关键的问。 我们先谈扩展。众所周知,工厂方法模式完全满足OCP,即它有非常良好的扩展性。那是否就说明了简单工厂模式就没有扩展性呢,答案是否定的。简单工厂模式同样具备良好的扩展性——扩展的时候仅需要修改少量的代码(修改工厂类的代码)就可以满足扩展性的要求了。尽管这没有完全满足OCP,但笔者认为不需要太拘泥于设计理论,要知道,sun提供的java官方工具包中也有想到多没有满足OCP的例子啊(java.util.Calendar这个抽象类就不满足OCP,具体原因大家可以分析下)。 然后我们从维护性的角度分析下。假如某个具体产品类需要进行一定的修改,很可能需要修改对应的工厂类。当同时需要修改多个产品类的时候,对工厂类的修改会变得相当麻烦(对号入座已经是个问题了)。反而简单工厂没有这些麻烦,当多个产品类需要修改是,简单工厂模式仍然仅仅需要修改唯一的工厂类(无论怎样都能改到满足要求吧,大不了把这个类重写)。 由以上的分析,笔者认为简单工厂模式更好用更方便些。当然这只是笔者的个人看法而已,毕竟公认的,工厂方法模式比简单工厂模式更“先进”。但有时过于先进的东西未必适合自己,这个见仁见智吧。 写在最后 本文仅讨论了两个常见的工厂模式,笔者很主观的分析了各自的优缺点,这必定会引起许多异议。如果对笔者观点有意见的,很欢迎跟贴批评指出。 其实究竟哪种模式更好,可能你会回答“都不好”,呵呵,别忘了,我们还有更“先进”的“抽象工厂模式”。。。 最后交代下版权信息。本文许多定义性的内容引用自《java与模式》(电子工业出版社,阎宏),这是本好书,有时间有机会希望大家可以好好看看,我在此书中是获益良多。另外笔者在写本文过程中还参考了《UML基础、案例与应用》(人民邮电出版社,Joseph Schmuller 著,李虎、赵龙刚译),除此外其余内容均为原创,转贴请注明“工大后院版权所有”。
/
本文档为【工厂设计模式】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索