上一篇Post效果不是很好,既然大家喜欢讨论,我就还是用讨论的形式来进行。
这次还是接着上一次的话题,封装,可能是因为没有表述清楚,所以导致了很多Tx有所疑问,所以这里更加详细的阐述我对于封装的看法。
===============================申明================================
本文讨论环境在纯面向对象语言环境下(静态类型语言,比如C#,JAVA),C++使用
者请注意某些和C++的不同之处。如果不加注释,本文的讨论不涉及ORM以及持久化等技术
==================================================================
首先什么是封装就不用多说了,上次说到,类是用来描述是什么,属性表示有什么,而行为表示能够执行什么动作的时候没有进一步对如何封装这些概念来做进一步的阐述。
对属性的封装:
属性表示对象的状态,而状态在程序里是使用数据来表示的,所以类中使用变量的来存储。所以一个类的内部成员变量是用来存储对象的状态的。
为了封装状态,我们需要将变量的访问性设置为private。
但是很多时候对象的某些状态是需要外界可见的(外部可见的状态,很容易理解,如果对象的状态都不清楚,那不是两眼一抹黑闷头操作),打个比方,汽车对象,起码来说,当前跑的速度,车身颜色,车牌号码都应该是外部能够了解的状态。那么,在java中,只有用方法来暴露了。到了后来就成了GetXXX,SetXXX方法,也就是POJO对属性的表示了。而在C#中专门提供了属性结构,其实在编译后还是两个方法。
属性不管在Java还是在C#中都是对状态的封装的一种形式。既满足了封装,也满足了对对象内部需要暴露状态访问的要求。
属性虽然说本质上就是两个方法(可以只有一个),但是属性的行为是有限制的(个人认为,当然你非要什么都写进去我也没法)。
其一,属性内的过程只操作属性所对应的内部状态的变量
其二,属性如果不需要接受外部的数据最好不要写set
属性内的过程是用来约束读取和写入状态数据的判断逻辑,所以应该是判断的代码而不是行为的代码。不要当成了普通的方法来写。
对行为的封装:
对象的行为,在面向对象的语言里使用方法来封装行为。我们Call一个方法,也就是通知了一个对象执行某种操作。这种操作由于是对象的方法在执行,所以对内部的状态可以全权操作。但是如果一个对象的行为设计到涉及到另个对象的状态,比如我们需要打开数据库首先述要判断Connection对象是处于什么的状态。所以如果是在行为里需要依赖另外对象的状态,那么就需要另外一个对象用属性暴露出这个状态出来。
但是,有一种方式我认为是不恰当的。比如,要保存对象的状态或者要设置对象的状态,都绕过了行为,而直接把属性当作公共出入口。从属性里读出来存入数据库,或者从数据库里读出来再挨个赋值给对象。最后再省略,这个类就连方法都没了。就我的看法,没有行为能力的人是死人(起码也是个植物人,高位截瘫什么的),没有行为能力的类,是死类:)。【个人觉得对一个对象的公有属性赋值,然后调用依赖于这些状态数据的方法是可以说得过去的,就和装好子弹扣扳机的过程一样,给这些属性赋值就是装子弹,执行方法就是扣扳机】
最后一个对象是不会有耦合的。对象多了,对象直接必要要打交道。在满足封装性的条件下,对象之间打交道主要通过两个接口,一个是属性,一个就是方法(属性方法都是外部对类状态改变的接口),当然在C#里还可以通过事件,不过事件在本质上还是对方法的调用。
最后我们必须来说说耦合的问题
耦合度是用来度量代码块之间联系的程度的标准
耦合度是从模块外部考察模块的独立性程度。它用来衡量多个模块间的相互联系。一般来说,耦合度应从以下三方面来考虑,即:
耦合内容的数量,即模块间发生联系的数据和代码的多少,同这些数据和代码发生联系的模块的多少,多的耦合强,少的耦合弱;
模块间的耦合类型。耦合类型有以下几种方式:
①独立耦合
②数据耦合
③控制耦合
④公共耦合
⑤内容耦合
下面重点对各种类型的耦合作进一步的说明。
(1)独立耦合
两个模块完全没联系
(2)数据耦合
指两个模块彼此交换数据。如一个模块的输出数据是另一个模块的输入数据,或一个模块带参数调用另一个模块,下层模块又返回参数。应该说,在一个软件系统中,此种耦合是不可避免的,且有其积极意义。因为任何功能的实现都离不开数据的产生、表示和传递。数据耦合的联系程度也较低。譬如调用方法
(3)控制耦合
若在调用过程中,两个模块间传递的不是数据参数而是控制参数,则模块间的关系即为控制耦合。控制耦合属于中等程度的耦合,较之数据耦合模块间的联系更为紧密。但控制耦合不是一种必须存在的耦合。当被调用模块接收到控制信息作为输入参数时,说明该模块内部存在多个并列的逻辑路径,即有多个功能。
举个例子
public void Action(bool param)
{
if(param)
{
//do something
}else
{
//do something
}
}
这个方法就存在控制耦合。
控制变量用以从多个功能中选择所要执行的部分,因而控制耦合是完全可以避免的。排除控制耦合可按如下步骤进行:
①找出模块调用时所用的一个或多个控制变量;
②在被调模块中根据控制变量找出所有的流程;
③将每一个流程分解为一个独立的模块;
④将原被调模块中的流程选择部分移到上层模块,变为调用判断。
通过以上变换,可以将控制耦合变为数据耦合。由于控制耦合增加了设计和理解的复杂程度,因此在模块设计时要尽量避免使用。当然,如果模块内每一个控制流程规模相对较小,彼此共性较多,使用控制耦合还是合算的。
(4)公共耦合
公共耦合又称公共环境耦合或数据区耦合。若多个模块对同一个数据区进行存取操作,它们之间的关系称为公共耦合。公共数据区可以是全程变量、共享的数据区、内存的公共复盖区、外存上的文件、物理设备等。当两个模块共享的数据很多,通过参数传递可能不方便时,可以使用公共耦合。公共耦合共享数据区的模块越多,数据区的规模越大,则耦合程度越强。公共耦合最弱的一种形式是:两个模块共享一个数据变量,一个模块只向里写数据,另一个模块只从里读数据。
当公共耦合程度很强时,会造成关系错综复杂,难以控制,错误传递机会增加,系统可靠性降低,可理解、维护性差。
(5)内容耦合
内容耦合是耦合程序最高的一种形式。若一个模块直接访问另一模块的内部代码或数据,即出现内容耦合。内容耦合的存在严重破坏了模块的独立性和系统的结构化,代码互相纠缠,运行错综复杂,程序的静态结构和动态结构很不一致,其恶劣结果往往不可预测。
内容耦合往往表现为以下几种形式:
①一个模块访问另一模块的内部代码或数据;
②一个模块不通过正常入口而转到另一个模块的内部(如使用GOTO语句或JMP指令直接进入另一模块内部,C#和JAVA里基本上不会出现,C++情况不明,望C++达人提供有效情报);
③两个模块有一部分代码重迭(可能出现在汇编程序中,在一些非结构化的高级语言,如COBOL中也可能出现);
④一个模块有多个入口(这意味着一个模块有多种功能)。
这里除了2,3两种情况,1和4都可能在面向对象的语言的代码里出现。
第一种情况主要是本来该类内部行为共享的公共方法被错误的设置为public并且被外部的对象使用了。或者是直接将一个对象的属性读取出来,运算的结果又重新写回了对象的另一个属性。还可能有其它情况,不过限于个人能力,暂不知晓,有知道的请告知。
就我个人来说,假如A类的对象有个Count属性,那么在累加的时候使用a.Count++我觉得还OK啦,还没有洁癖到非要去弄一个Upgrade的方法上去,当然如果这个Upgrade的动作还涉及到其他的状态,那就还是多个方法出来好了。
一般讲,在模块划分时,应当尽量使用数据耦合。少用控制耦合(尽量转成数据耦合),限制公共耦合的范围,完全不用内容耦合。
所以说封装并不是表明就不耦合了,但是封装可以降低耦合度。对于耦合度来说我们是应该尽量降低的(在时间金钱允许的情况下),低耦合代表着在应对变化时我们能够更加从容应对。
分享到:
相关推荐
在编程领域,尤其是在C#这样的面向对象编程语言中,封装是一种基本的编程原则,它能够帮助我们构建更清晰、更可维护的代码。本示例是针对初学者设计的,旨在展示如何通过创建和使用类来封装数据库操作,从而提高代码...
总之,了解和掌握Protel DXP中的封装库对于初学者来说非常重要,它不仅可以帮助设计师快速上手,还能有效地提高电路板设计的质量和效率。通过合理利用现有的封装资源,并学习如何高效地管理和导入外部库,可以极大地...
在电子设计领域,PCB(Printed Circuit Board)封装是一个至关重要的概念,它是指电子元器件在PCB设计中的二维图形表示。对于PCB制图的初学者来说,理解并熟练掌握PCB封装是非常必要的,因为正确的封装选择直接影响...
【GHOST系统封装详解】 ...通过这个详细的GHOST系统封装图文教程,初学者将能全面了解封装过程,并逐步掌握这项实用技能。实践出真知,理论结合实际操作,相信不久后你也能熟练地运用GHOST进行系统封装,提升工作效率。
微电子器件封装:封装材料与封装技术.pdf
- 这对于初学者来说是一个极大的便利,可以让开发者将更多精力集中在业务逻辑而非底层细节上。 3. **跨平台性**: - Java程序可以在任何支持Java虚拟机(JVM)的平台上运行,无需重新编译。 - 这一点极大地提高了...
在Java编程语言中,学习和理解基本词汇是初学者入门的关键。以下是一些核心概念的详细解释: 1. **Abstract Window Toolkit (AWT)**:AWT是Java早期提供的一种图形用户界面(GUI)工具包,它使用本地操作系统提供的...
对于Java初学者来说,选择合适的书籍进行学习是至关重要的一步。好的书籍不仅能够帮助我们打下坚实的基础,还...因此,对于初学者而言,耐心地研读这些书籍,并结合实际项目进行练习,将会是一个非常有价值的学习过程。
【JAVA初学者_扫雷源码】是一个适合初级JAVA学习者参考的项目,它展示了如何用JAVA编程语言实现经典游戏“扫雷”。这个项目对于理解JAVA基础语法、控制流程、面向对象编程等概念非常有帮助。 1. **JAVA基础语法**:...
在本文中,我们将深入探讨如何使用Halcon连接相机并在Visual Studio (VS)中进行界面封装,这非常适合初学者作为入门教程。Halcon是一款强大的机器视觉软件,广泛应用于自动化生产和质量检测领域。通过VB.NET,我们...
下面我们将详细探讨Java初学者在220个实例中可能会遇到的知识点。 1. **基础语法**:包括变量声明、数据类型(如整型、浮点型、字符型、布尔型)、运算符(算术、比较、逻辑、位操作等)、流程控制(如if-else、...
本资源提供的是专为Advanced Design System(AD)设计的"ESOP封装",一个完整的三维PCB封装库。AD是一款广泛应用的高级电路设计软件,具备强大的PCB设计功能,而封装库则包含了各种元器件的形状和电气接口信息,使得...
这个“java初学者完整代码+注释5”压缩包文件显然是为那些刚开始学习Java的人设计的,包含了21个课程的学习内容。下面,我们将深入探讨这些标签所涵盖的知识点,并结合DAY5的子文件,讨论一些可能包含的Java基础概念...
Java编程是IT领域中最受欢迎的语言之一,尤其对于初学者来说,它是学习编程的良好起点。"初学者java作业题目"这个主题涵盖了多个Java编程的基础概念,旨在帮助初学者巩固语法、理解面向对象编程以及掌握基本的编程...
这个封装类可能包括建立连接、执行SQL语句、获取数据行、关闭连接等基本操作,并且设计得足够简单,方便初学者理解和使用。 描述中的"接口非常简单,十分易用"意味着封装类的设计者已经考虑到了易用性,尽可能减少...
本文将详细阐述“变压器封装”和“立创标准封装库”的相关知识点,帮助读者理解这两个概念及其在实际设计中的应用。 首先,让我们了解什么是变压器封装。在电子电路中,变压器是一种利用电磁感应原理进行电压、电流...
《Java初学者实战指南——180个简单实例解析》 Java编程语言以其跨平台、面向对象和强大的功能,成为了全球范围内广泛使用的编程语言之一,尤其对于初学者来说,掌握Java的基本概念和语法是入门的关键。这个名为...
**Selenium初学者指南** Selenium是一款强大的自动化测试工具,尤其在Web应用程序的测试领域,它占据了重要地位。本指南专为初次接触Selenium的读者设计,旨在帮助你们快速掌握这个强大的工具,从而提高测试效率,...
这个“HTTPClient的一个封装”显然指的是对Apache HttpClient库进行了定制化处理,以适应特定项目需求或者简化API使用。下面将详细讨论HttpClient的核心概念、封装的目的以及可能实现的方式。 HttpClient是Apache...