面向对象设计(OOD)思想
如何合理地进行类设计以降低类的藕合度

(4)BBS论坛系统中的BBS信息发表的职责分配示例
(2)脆弱性 当在系统中的某处做了改动后,却导致系统的另外的 多个模块也发生了“连锁”的变化。 (3)不可重用性 很难在别的应用程序中重用系统中的某个模块,因为 不能将它从现有的应用程序中独立地提取出来——会产生 出“拔出萝卜带出泥”的效果。 3、依赖和耦合(Dependency and Coupling) (1)什么是依赖 Rose的帮助文档上是这样定义“依赖”关系的:“依 赖描述了两个模型元素之间的关系,如果被依赖的模型元 素发生变化就会影响到另一个模型元素。 下图为计算机类与其它类之间所产生的依赖关系示例 图:
5、系统设计的追求目标是尽可能降低过强的耦合关系 (1)为什么要“解藕” 过强的耦合关系(如一个模块的变化会造成一个或多 个其他模块也同时发生变化的依赖关系)会对软件系 统的质量造成很大的危害; 特别是当需求发生变化时,代码的维护成本将非常高。 (2)过强的耦合关系的代码示例
(3)控制和消除不必要的耦合关系 设计人员必须想尽办法控制和消解不必要的耦合,特 别是那种会导致其它模块发生不可控变化的依赖关系。
1、什么是好的模块类设计---Peter Code(CODE99) 一个良好的模块类设计,一般应该要具有如下基本的要 求——高内聚和低耦合(High Cohesion and Low Coupling) 的设计结果。 (1)可扩展性(Extensibility) 系统很容易添加新的功能实现,从而很容易扩展。 (2)灵活性(Flexibility) 能够很方便地适应不同的应用环境。 (3)可插入性(Pluggablity) 容易将一个类抽出去,同时将另一个有同样接口的实现 类添加进来而实现功能实现的替换。 2、不良的模块类设计所导致的结果 (1)缺乏灵活性 难添加新的功能,因为每一处改动就会影响到系统中过多 的模块,此时则认为该系统缺乏灵活性。
浅谈OOA,OOD,OOP的理解

浅谈OOA,OOD,OOP的理解OOA(⾯向对象分析)、OOD(⾯向对象设计)、OOP(⾯向对象编程),这3个概念,对于我们JAVA程序员来讲,或多或少应该都有所了解,或者说⾄少都听说过。
但是要谈到对其理解,可能对于多数⼊⾏不深的从业者来说,确实不是那么容易做到。
特别是对于绝⼤多数的3年以内的低中级软件⼯程师⽽⾔。
因为他们的⼯作更多是需要按照项⽬经理分配的任务来编写功能代码,很少有多余的时间去阅读或者思考⼀些概念性的东西。
说起这个问题,我也在⽹络上也搜索过很多的资料,⼤多摘录⾄书籍,⽐较官⽅化。
让初学者⽆从理解。
为了⼴⼤的新从业者或者应聘者,在这⾥,我们以⼀种实例的⽅式来对这3个概念进⾏重新的阐述:业务场景:建⾏卡持有者,张三与李四两⼈,现在需要张三给李四转账⼈民币5000元整。
按照业务分析后的流程图如下:对于分析业务流程,常见的2种:⾯向过程分析(POA),⾯向对象分析(OOA)⾯向过程分析(Procedure Oriented Analysis):是⼀种以过程为中⼼的编程思想,以数据流向为主要导向。
为了解决问题,将解决问题的业务过程,按照⼀定的顺序划分成为⼀个⼜⼀个的事件,然后再封装成⼀个⼜⼀个的函数,最后由⼀个函数统⼀的按照顺序⼀步⼀步的调⽤即可。
在⾯向过程分析中,顺序很重要,要实现功能只需要按照⼀定的顺序相互调⽤函数即可。
上述业务场景按照⾯向过程分析出来的结果就是:1. 程序检查张三卡中余额是否⾜够5000元⼈民币(事件1,满⾜则调⽤事件2)2. 程序从张三卡中扣除5000元⼈民币(事件2)3. 程序向李四卡中加⼊5000元⼈民币(事件3)4. 程序检测李四卡中是否正常⼊账(事件4,满⾜则结束整个业务)5. 程序向张三卡中加⼊5000元⼈民币(事件5)在上述过程中,我们将这个业务过程,分成了5个步骤,也叫做5个事件,那么如果需要在程序中完成该转账业务的话,那么我们只需要按照1-2-3-4-5这样的顺序依次调⽤函数⽅法即可。
河南理工大学软件工程面向对象设计

2016/12/191第11章面向对象设计面向对象设计(OOD ,Object-Oriented Design )是面向对象分析到实现的一个桥梁。
面向对象分析是将用户需求经过分析后,建立问题域精确模型的过程;而面向对象设计则是根据面向对象分析得到的需求模型,建立求解域模型的过程。
即分析必须搞清楚系统“做什么”,而设计必须搞清楚系统“怎么做”,从分析到设计不是传统方法的转换,而是平滑(无缝)过渡,而求解域模型是系统实现的依据。
2⏹面向对象设计可分为系统设计和类(对象)设计。
⏹系统设计是高层设计,主要确定实现系统的策略和目标系统的高层结构。
类(对象)设计是低层设计,主要确定解空间中的类、关联、接口形式及实现服务的算法;⏹高层设计主要确定系统的结构、用户界面,即用来构造系统的总的模型,并把任务分配给系统的各个子系统。
3本章内容⏹面向对象设计的准则⏹启发规则⏹软件重用⏹系统分解⏹设计问题域子系统⏹设计人机交互子系统⏹设计任务管理子系统⏹设计数据管理子系统⏹设计类中的服务⏹设计关联⏹设计优化4⏹(1)模块化⏹在面向对象开发方法中,将对象定义为模块。
对象把数据结构和作用在数据上的操作(方法)封装起来构成模块。
对象是组成系统的基本模块。
⏹(2)抽象⏹类是一种抽象数据类型,在该数据类型之上,可以创建对象(类的成员)。
类包含相似对象的共同属性和服务,它对外定义了公共接口,构成了类的规格说明(即协议),供外界合法访问。
⏹(3)信息隐藏⏹在面向对象方法中,对象是属性和服务的封装体,这就实现了信息隐藏。
类结构分离了接口与实现,类的属性的表示方法和操作的实现算法,对于类的用户来说,都应该是隐藏的,用户只能通过公共接口访问类中的属性。
5⏹(4)弱耦合⏹耦合是指一个软件结构内不同模块之间互连的依赖关系。
依赖关系越多耦合度越强,依赖关系越少耦合度越弱。
在面向对象方法中,对象是最基本的模块。
不同对象之间相互关联的依赖关系表示了耦合度。
.NET4.0 面向对象基础

4.0 面向对象基础早期的语言开发思想,都是针对某一件事,而一步一步的来完成,称之为“面向过程开发”。
而面向对象是将某一件事,以一个整体的对象化进行考虑,按照不同的动作使用不同的方法来完成。
另外,面向对象可以认为是一种哲学的思想,将客观实体和实体之间的联系构成了现实世界的所有问题,而每一个实体都可以抽象为对象。
这种思想尽可能地按照人类认识世界的方法和思维方式来分析和解决问题,使人们分析、设计一个系统的方法尽可能接近认识一个系统的方法。
1.面向对象分析和设计面向对象的分析和设计(Object Orient Analysis & Design,OOAD)是现代软件企业广为采用的一项有效技术,其中包含了面向对象分析和面向对象设计两个方法。
OOAD方法要求在设计中要映射现实世界中指定问题域中的对象和实体,例如:乘客、公交汽车和售票员等。
这就需要设计要尽可能地接近现实世界,即以最自然的方式表述实体。
面向对象分析(OOA)是指利用面向对象的概念和方法为软件需求构造出关系模型,以使用户需求逐步明确、细化、一致性、完整性的分析过程。
分析的过程也是提取需求的过程,主要包括理解、表达和验证。
由于现实世界中存在的问题通常比较复杂,所以在分析过程中需要进行交流,并且也需要具有随意性和非形式化等特点。
而对于软件需求说明的正确性、完整性和有效性就需要进一步验证,以便及时加以修正。
面向对象分析中构造的模型主要分为对象模型、动态模型和功能模型。
其关键是识别出问题域中的对象,在分析它们之间相互关系之后建立起问题域的简洁、周详、可以理解的模型。
对象该模型通常由5个层次组成:类与对象层、属性层、服务层、结构层和主题层,如图3-1所示。
主题层类与对象层结构层属性层服务层图3-1 复杂问题的对象模型的这5个层次对应着在面向对象分析过程中,构造对象模型的5项主要活动,如发现对象、定义类、定义属性、定义服务、建立结构。
面向对象的分析过程如图3-2所示。
第11章--OOD

及时撤消错误动作,消除错误动作造成的后果。
无须记忆:不应该要求用户记住在某个窗口中显示的 信息,然后再用到另一个窗口中,这是软件系统的责
任而不是用户的任务。
1
面向对象设计的准则
启发规则 系统分解 设计问题域子系统 设计人_机交互子系统 设计任务管理子系统
7
2
设计数据管理子系统
设计类中的服务
3
8
4
9
设计关联 设计优化
5
10
6
11 面向对象分析与设计实例
11.1 面向对象设计的准则
优秀设计是指权衡了各种因素,从而使得系统在 其整个生命周期中的总开销最小的设计。
图8.2
典型的面向对象设计模型
子系统之间的两种交互方式
在软件系统中,子系统之间的交互有两种可能的方式: 分别是客户—供应商(Client_supplier)关系
和平等伙伴(peer_to_peer)关系。
总的说来,单向交互比双向交互更容易理解,也更容易 设计和修改,因此应该尽量使用客户—供应商关系。
减少步骤:应使用户为做某件事情而需敲击键盘
的次数、点按鼠标的次数、或者下拉菜单的距离, 都减至最少。 还应使得技术水平不同的用户,为获得有意义的 结果所需使用的时间都减至最少。特别应该为熟
练用户提供简捷的操作方法(例如,热键)。
及时提供反馈信息:每当用户等待系统完成一项工作
时,系统都应该向用户提供有意义的、及时的反馈信
对面向对象分析所得出的问题域模型作的补充或修改:
OO思想

多态机制
类关系与类图
类之间的四种基本关系(约束)
关联(association) 泛化(generalization) 实现(realization) 依赖(dependence)
类图(Class diagram)是最常用的UML图,显示出类、接口以及它们之间的 静态结构和关系;它用于描述系统的结构化设计。 类图以一种更一般的方式指定了系统的任何合法状态都必须满足的特性 对象图是类图的一个实例,对象图中的链接满足类图中定义的各种约束 对象图是对象与链接的集合,显示系统的一个特定状态
2
OO的基本概念
类 对象 封装 继承 重载 多态
3
类
是对具有相同数据和相同操作的一组相似对象的 抽象定义 理解
是对具有相同属性(不同值)和行为的一组对象的描述 是支持继承的抽象数据类型,是对象实例化的模版 一个对象就是类的一个实例 类定义了对象的特征,分为属性和操作 属性,定义类实例存储的数据,是对客观实体所具 有共同性质的抽象,类实例化的每个对象都有自己 特有的属性值 操作:也称方法,定义类实例的动态行为(算法)
两种重载
public
重载机制
提高OO程序灵活性和可读性
12
多态(Polymorphism)
描述:
通过重写(override)父类的同名操作,使子类对象和父类 对象接受同一消息,却提供不同服务 不同层次的类共享一个行为(函数名、参数和返回值类型 都相同),但行为实现却不同
动态联编(dynamic binding),也称滞后联编(late binging) 运行时,消息发送对象不知道谁将接收消息,依赖接 收对象以一种恰当的方式解释消息,根据消息接收对象所 属的类,决定实现什么样的行为,享受什么样的服务 增强OO系统的灵活性,减少信息冗余,提高软件的可重 用性和可扩充性
软件工程导论课件之第11章 面向对象设计(第五版)(张海藩编著)

如果对象之间的耦合通过消息连接来实现,则这种耦合 就是交互耦合。
交互耦合应尽可能松散 。
继承耦合
与交互耦合相反,应该提高继承耦合程度。 继承是一般化类与特殊类之间耦合的一种形式。通过继
承关系结合起来的基类和派生类,构成了系统中粒度更 大的模块。彼此之间应该越紧密越好。
5. 强内聚 内聚衡量一个模块内各个元素彼此结合的紧密程度。
多态重用
利用多态性不仅可以使对象的对外接口更加一般化, 从而降低了消息连接的复杂程度,而且还提供了一 种简便可靠的软构件组合机制。
11.3.3 软件重用的效益
1. 质量 随着每一次重用,都会有一些错误被发现并被清除,
构件的质量也会随之改善。 2. 生产率 当把可重用的软件成分应用于软件开发的全过程时,
6. 可重用
软件重用是提高软件开发生产率和目标系统质 量的重要途径。
重用基本上从设计阶段开始。
重用有两方面的含义:
一是尽量使用已有的类(包括开发环境提供的类库, 及以往开发类似系统时创建的类),
二是如果确实需要创建新类,则在设计这些新类的 协议时,应该考虑将来的可重复使用性。
11.2 启发规则
3. 典型的可重用软件成分 项目计划 成本估计 体系结构 需求模型和规格说明 设计 源代码 用户文档和技术文档 用户界面 数据 测试用例
11.3.2 类构件
面向对象技术中的“类”,是比较理想的可重 用软构件,称之为类构件。
1. 可重用软构件应具备的特点
模块独立性强 具有高度可塑性 接口清晰、简明、可靠
软件工程导论课件之第11章 面向对象设计 (第五版)(张海藩编著)
分析是提取和整理用户需求,并建立问题域精 确模型的过程。
设计则是把分析阶段得到的需求转变成符合成 本和质量要求的、抽象的系统实现方案的过程。
12 第十二讲 OOA OOD OOP

阶段主要输出物:代码和开发文档
本次课程小结及上机安排
重点 了解并基本掌握OOA/OOD/OOP的思想
上机练习
1
n
概念模型
Account Userid Accountid Balance Currency Password Type InterestRate LastModified
概念类
面向对象分析OOA
需求 分析
查询 ATM 图形界面
插入银行卡
帐户
数据访问接口
…… ……
输入密码 提示输入密码 验证用户密码 读取帐户信息
Account 1 -Accountid:string -password:string -count:int +validate(accountno,pass) +getBalance()
软件类
DAO +getAccountInfo(accountno)
面向对象分析OOD
Customer Userid Username Address Phone Mobile Email Idtype IDNum 1 n Account Userid Accountid Balance Currency Password Type InterestRate LastModified
查询
1.客户插入银行 卡 2.系统提示客户 输入密码 3.客户输入密码 4.系统验证 ……
点击查询按钮
提示选择功能 读取帐户余额
显示帐户余额
序列图
面向对象分析OOD
OOD:Object-Oriented Design,面向对象设计 设计阶段则主要是确定实现用户需求的方法,即怎样做才 能满足用户需求,并构造出系统的实现蓝图。 面向对象设计引入了面向对象的概念和原则来指导设计工 作。OOD首先从OOA的结果开始,并将其从问题域映射到实现域, 为满足实现的需要,还要增加一些类,并对原有类及属性进行调 整。此外,还要完成应用控制、人机交互界面的设计等。 OOD的主要工作有: 1)问题域部分的设计主要是对OOA结果进行改进和精化,有 以下几个方面:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
面向对象设计(OOD)思想(C#)面向对象分析(道法自然)面向对象的思维方式:面向对象是围绕对象和类来分析、设计软件系统的。
面向对象分析:面向对象分析的主要任务是根基用户的需求,建立一个准确的、完整的、一致的系统模型。
在面向对象的分析过程里,项目组通过分析软件的功能性需求,得到一个理想化的系统模型,该模型更多的侧重于描述我们需求解决的问题是什么---我们称这种模型为分析模型。
面向对象分析与面向对象设计的区别:1、在侧重点上,面向对象分析侧重于理解问题,描述软件做什么,而面向对象设计侧重于理解解决方案,描述软件如何做。
2、面向对象分析一般只考虑理想的设计,不关心技术和实现的细节,而面向对象设计更具体、更详细、更接近真实的代码的设计方案。
3、在设计结果的描述方式上,分析阶段侧重描述对象的行为,设计阶段侧重于描述对象的属性和方法。
4、面向对象分析只关注功能性需求,而面向对象设计既关注功能性需求,也关注非功能性需求。
5、面向对象分析的产生的系统模型通常规模较小,而面向对象的设计产生的系统模型规模较大,内容也比较完整、详尽。
用例驱动的面向对象分析:面向对象分析的过程包括:1、从用例中提取实体对象和实体类。
提取实体对象的方法,依据用例描述中出现的名词和名词短语来提取实体对象,必须对原始的名词和名词短语进行筛选。
得到实体对象后,对实体对象进行归纳、抽象出实体类。
2、提取属性3、提取关系4、添加边界类5、添加控制类6、绘制类图7、绘制顺序图8、编制术语表有了思想才能飞翔,缺乏灵活就象少了轮子的汽车,难以飞奔。
为了更好的理解设计思想,结合一个尽可能简洁的实例来说明OOD、设计模式及重构。
通过下面的代码,详细地阐述面向对象设计思想。
一、传统过程化设计思想假定我们要设计一个媒体播放器(只从软件设计的角度,不涉及硬件)。
该媒体播放器目前只支持音频文件mp3和wav。
按照结构化设计思想,设计出来的播放器的代码如下:面向对象设计(OOD)思想(C#)有了思想才能飞翔,缺乏灵活就象少了轮子的汽车,难以飞奔。
为了更好的理解设计思想,结合一个尽可能简洁的实例来说明OOD、设计模式及重构。
通过下面的代码,详细地阐述面向对象设计思想。
一、传统过程化设计思想假定我们要设计一个媒体播放器(只从软件设计的角度,不涉及硬件)。
该媒体播放器目前只支持音频文件mp3和wav。
按照结构化设计思想,设计出来的播放器的代码如下:Code从传统的过程化设计思想来看,这是一段既实用又简洁的代码。
如果,客户又提出新的要求:要播放器不仅仅播放mp3和wav文件,还要播放其他音频文件如wma、mp4等,为此我们要不断地增加相应地播放方法和修改条件语句,直止条件语句足够长。
如果,客户感到这个媒体播放器功能太少了,只能闻其声,不能见其人,太单一。
如果在听着优美音乐的同时又能看到歌唱者潇洒、英俊的舞姿那就更好了。
从代码设计的角度看,他们希望媒体播放器支持视频文件了。
也许你会想,不会再增加视频这方面的代码,可以,在增加视频媒体的播放方法,在修改条件判断语句,如果还有其他,还可以同样地增加、修改。
到此你也许会提出,要是不修改或很少修改原来的代码就能增添其他功能该多好啊!这样看,原来的软件设计结构似乎有点问题。
事实上,随着功能的不断增加,你越来越发现这个设计非常的糟糕,因为它根本没有为未来的需求变更提供最起码的扩展。
为了应接不暇的变更需求,你不得不不厌其烦地修改原来的代码,使其适应需求变化,甚至在修改代码时,由于过多的代码依赖关系弄得人焦头烂额,直止一塌糊涂。
二、面向对象设计思想还是以设计一个媒体播放器为例,设计要求相同。
不访我们换个设计思路利用面向对象设计思想(OOD)来做做看如何!根据OOD的思想,我们应该把mp3和wav分别看作是两个独立的对象。
代码设计如下:Code现在我们重构代码,建立统一的Play()方法,(在后面的设计中,你会发现这样改名是多么的重要!)更改媒体播放类MediaPlayer的代码。
如果这样的设计代码,实质上没有多大的变化,只是对原来过程化设计思想的一种替代,并没有击中要害,亦然没有灵活性、可扩展性。
2.1单向分派技术的应用(在这里用类的多态来实现的)我们不访这样设想:既然mp3和wav都属于音频文件,都具有音频文件的共性,应该建立一个共同的AudioMedia父类。
1public class AudioMedia2{3public void Play()4 {5 MessageBox.Show("Play the AudioMedia file.");6 }7}现在引入继承思想,OOD就有点雏形了(不是说有了继承就有了OOD思想,这里只是从继承的角度谈一谈OOD思想,当然从其他角度如合成、聚合等角度也能很好地体现OOD思想)。
其实在现实生活中,我们的播放器播放的只能是某种具体类型的音频文件如mp3,因此这个AudioMedia类只能是音频媒体的一个抽象化概念,并没有实际的使用情况。
对应在OOD设计中,既这个类永远不会被实例化。
为此我们应将其改为抽象类,如下:Code到此,我们通过单向分派技术使OOD思想得到进一步的体现。
现在的设计,即满足了类之间的层次关系,又保证了类的最小化原则,同时又体现了面向对象设计原则(开—闭原则、里氏代换原则)更利于扩展。
(止此,你会发现play方法名的更改是多么必要)。
如果现在又增加了对WMA、MP4等音频文件的播放,只需要设计WMA类,MP4类,并继承AudioMedia,在相应的子类中重写Play方法就可以了,MediaPlayer类对象的Play方法根本不用任何改变。
如果让媒体播放器能够支持视频文件,必须另外设计视频媒体的类。
因视频文件和音频文件有很多不同的地方,不可能让视频继承音频。
假设我们播放器支持RM和MPEG格式的视频。
视频类代码如下:Code这样设计还是有点糟糕,这样就无法实用原有的MediaPlayer类了。
因为你要播放的视频RM文件并不是音频媒体AudioMedia的子类。
不过,我们可以这样想,无论音频媒体还是视频媒体都是媒体,有很多相似的功能,如播放、暂停、停止等,为此我们把“媒体”这个概念抽象出来做为一个接口。
(虽然也可以用抽象类,但在C#里只支持类的单继承,不过c#支持接口的多继承)。
根据接口的定义,你完全可以将相同功能的一系列对象实现同一个接口。
让音频媒体类及视频媒体类都继承媒体这个接口。
代码如下:Code现在看来,程序是不是有很大的灵活性和可扩展性了。
总结一下,从MediaPlayer类的演变,我们可以得出这样一个结论:在调用类对象的属性和方法时,尽量避免将具体类对象作为传递参数,而应传递其抽象对象,更好地是传递接口,将实际的调用和具体对象完全剥离开,这样可以很好地体现了软件工程的灵活性、扩展性。
现在看起来似乎很完美了,但我们忽略了MediaPlayer的调用者这个事实。
仍然需要条件语句来实现。
例如,在客户端程序代码中,用户通过选择cbbMediaType组合框的选项,决定播放音频媒体还是视频媒体,然后单击Play按钮执行。
Code2.2设计模式、条件外置及反射技术的应用随着需求的增加,程序将会越来越复杂。
此时就应调整设计思想,充分考虑到代码的重构和设计模式的应用。
最后当设计渐趋完美后,你会发现,即使需求不断增加,你也可以神清气爽,不用为代码设计而烦恼了。
为了实现软件工程的三个主要目标:重用性、灵活性和扩展性。
我们不访用设计模式、条件外置及反射来实现。
使用工厂模式,能够很好地根据需要,调用不同的对象(即动态调用),保证了代码的灵活性。
虽然这里有两种不同类型的媒体AudioMedia和VideoMedia(以后可能更多),但它们同时又都实现IMedia接口,所以我们可以将其视为一种产品。
媒体工厂接口如下:public interface IMediaFactory{IMedia CreateMedia();}然后为具体的媒体文件对象搭建工厂,并统一实现媒体工厂接口:Code写到这里,也许有人会问,为什么不直接给AudioMedia和VideoMedia类搭建工厂呢?很简单,因为在AudioMedia和VideoMedia中,分别还有不同的类型派生,如果为它们搭建工厂,则在CreateMedia()方法中,仍然要使用条件判断语句,代码缺乏灵活性,不利扩展。
还有一个问题,就是真的有必要实现AudioMedia和VideoMedia两个抽象类吗?让其子类直接实现接口不是更简单?对于本文提到的需求,是能实现的。
但不排除AudioMedia和Vi deoMedia它们还会存在其他区别,如音频文件还需给声卡提供接口,而视频文件还需给显卡提供接口。
如果让MP3、WAV、RM、MPEG直接实现IMedia接口,而不通过AudioMedia和VideoMedia,在满足其它需求的设计上也是不合理的。
现在客户端程序代码发生了稍许的改变:Code到这里,我们再回过头来看MediaPlayer类。
这个类中通过单向分派,根据传递参数的不同,分别实现了不同对象的Play方法。
在不用工厂模式时,这个类对象会运行得很好。
作为一个类库或组件设计者来看,他提供了一个不错的接口,供客户端程序调用。
利用工厂模式后,现在看来MediaPlayer类已经多余。
所以,我们要记住的是,重构并不仅仅是往原来的代码添加新的内容。
当我们发现一些不必要的设计时,还需要果断地删掉这些冗余代码。
修改后的代码如下:Code如果你在最开始没有体会到IMedia接口的好处,在这里你应该已经明白了。
我们在工厂模式中用到了该接口;而在客户端程序中,仍然要使用该接口。
使用接口有什么好处?那就是你的主程序可以在没有具体业务类的时候,同样可以编译通过。
因此,即使你增加了新的业务,你的客户端程序是不用改动的。
不过,这样写客户端代码还是不够理想的,依然不够灵活,在判断具体创建哪个工厂的时候,仍需条件判断。
现在看来,如果执行者没有完全和具体类分开,一旦更改了具体类的业务,例如增加了新的工厂类,仍然需要更改客户端程序代码。
我们可以通过反射技术、条件外置很好地做到客户端的灵活性。
条件外置来实现,即通过应用程序的配置文件来实现。
我们可以把每种媒体文件类的类型信息放在配置文件中,然后根据配置文件来选择创建具体的对象。
并且,这种创建对象的方法将使用反射技术来完成。
首先,创建配置文件:Code然后,在客户端程序代码中,自定义一个初始化方法如:InitMediaType(),读取配置文件的所有key值,填充cbbMediaType组合框控件中:Code最后,更改客户端程序的Play按钮单击事件:Code这样可以很好地体现了软件工程的三个主要目标:重用性、灵活性和扩展性。