在PHP开发中养成7个面向对象的好习惯

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

如果您尚未打算用OO原则创建应用程序,则使用PHP的面向对象(OO)的语言特性,这7个习惯将帮助您开始在过程编程与OO编程之间进行转换。在PHP编程早期,PHP代码在本质上是限于面向过程的。过程代码的特征在于使用过程构建应用程序块。过程通过允许过程之间的调用提供某种程度的重用。但是,没有面向对象的语言构造,程序员仍然可以把OO特性引入到PHP代码中。这样做有点困难并且会使代码难于阅读,因为它是混合范例(含有伪OO设计的过程语言)。使用PHP代码中的OO构造—例如能够定义和使用类、能够构建使用继承的类之间的关系以及能够定义接口—可以更轻松地构建符合优秀OO实践的代码。虽然没有过多模块化的纯过程设计运行得很好,但是OO设计的优点表现在维护上。由于典型应用程序的大部分生命周期都花费在维护上,因此代码维护是应用程序生命周期的重要部分。并且在开发过程中代码维护很容易被遗忘。如果在应用程序开发和部署方面存在竞争,那么长期可维护性可能被放在比较次要的地位。模块化—优秀OO设计的主要特性之一—可以帮助完成这样的维护。模块化将帮助封装更改,这样可以随着时间的推移更轻松地扩展和修改应用程序。总的来说,虽然构建OO软件的习惯不止7个,但是遵循这里的7个习惯可以使代码符合基本OO设计标准。它们将为您提供更牢固的基础,在此基础之上建立更多OO习惯并构建可轻松维护与扩展的软件。这些习惯针对模块化的几个主要特性。有关独立于语言的OO设计优点的更多信息,请参阅参考资料。7个优秀PHPOO习惯包括:保持谦虚。做个好邻居。避免看到美杜莎。利用最弱的链接。您是橡皮;我是胶水。限制传播。考虑使用模式。保持谦虚保持谦虚指避免在类实现和函数实现中暴露自己。隐藏您的信息是一项基本习惯。如果不能养成隐藏实现细节的习惯,那么将很难养成任何其他习惯。信息隐藏也称为封装。直接公开公共字段是一个坏习惯的原因有很多,最重要的原因是让您在实现更改中没有应有的选择。使用OO概念隔离更改,而封装在确保所作更改在本质上不是病毒性(viral)更改方面扮演不可或缺的角色。病毒性更改是开始时很小的更改—如将保存三个元素的数组更改为一个只包含两个元素的数组。突然,您发现需要更改越来越多的代码以适应本应十分微不足道的更改。开始隐藏信息的一种简单方法是保持字段私有并且用公共访问方法公开这些字段,就像家中的窗户一样。并没有让整面墙都朝外部开放,而只打开一两扇窗户(我将在“好习惯:使用公共访问方法”中介绍访问方法的更多信息)。除了允许您的实现隐藏在更改之后外,使用公共访问方法而非直接公开字段将允许您在基本实现的基础上进行构建,方法为覆盖访问方法的实现以执行略微不同于父方法的行为。它还允许您构建一个抽象实现,从而使实际实现委托给覆盖基本实现的类。坏习惯:公开公共字段在清单1的坏代码示例中,Person对象的字段被直接公开为公共字段而非使用访问方法。虽然此行为十分诱人,尤其对于轻量级数据对象来说更是如此,但是它将对您提出限制。清单1.公开公共字段的坏习惯?phpclassPerson{public$prefix;public$givenName;public$familyName;public$suffix;}$person=newPerson();$person-prefix=Mr.;$person-givenName=John;echo($person-prefix);echo($person-givenName);?如果对象有任何更改,则使用该对象的所有代码也都需要更改。例如,如果某人的教名、姓氏和其他名字被封装到PersonName对象中,则需要修改所有代码以适应更改。好习惯:使用公共访问方法通过使用优秀的OO习惯(参见清单2),同一个对象现在拥有私有字段而非公共字段,并且通过称为访问方法的get和set公共方法谨慎地向外界公开私有字段。这些访问方法现在提供了一种从PHP类中获取信息的公共方法,这样在实现发生更改时,更改使用类的所有代码的需求很可能变小。清单2.使用公共访问方法的好习惯?phpclassPerson{private$prefix;private$givenName;private$familyName;private$suffix;publicfunctionsetPrefix($prefix){$this-prefix=$prefix;}publicfunctiongetPrefix(){return$this-prefix;}publicfunctionsetGivenName($gn){$this-givenName=$gn;}publicfunctiongetGivenName(){return$this-givenName;}publicfunctionsetFamilyName($fn){$this-familyName=$fn;}publicfunctiongetFamilyName(){return$this-familyName;}publicfunctionsetSuffix($suffix){$this-suffix=$suffix;}publicfunctiongetSuffix(){return$suffix;}}$person=newPerson();$person-setPrefix(Mr.);$person-setGivenName(John);echo($person-getPrefix());echo($person-getGivenName());?乍看之下,这段代码可能会完成大量工作,并且实际上可能更多是在前端的工作。但是,通常,使用优秀的OO习惯从长远来看十分划算,因为将极大地巩固未来更改。在清单3中所示的代码版本中,我已经更改了内部实现以使用名称部件的关联数组。比较理想的情况是,我希望拥有错误处理并且更仔细地检查元素是否存在,但是本例的目的在于展示使用我的类的代码无需更改的程度—代码并没有察觉到类发生更改。记住采用OO习惯的原因是要谨慎封装更改,这样代码将更具有可扩展性并且更容易维护。清单3.使用不同内部实现的另一个示例?phpclassPerson{private$personName=array();publicfunctionsetPrefix($prefix){$this-personName['prefix']=$prefix;}publicfunctiongetPrefix(){return$this-personName['prefix'];}publicfunctionsetGivenName($gn){$this-personName['givenName']=$gn;}publicfunctiongetGivenName(){return$this-personName['givenName'];}/*etc...*/}/**Eventhoughtheinternalimplementationchanged,thecodeherestaysexactly*thesame.ThechangehasbeenencapsulatedonlytothePersonclass.*/$person=newPerson();$person-setPrefix(Mr.);$person-setGivenName(John);echo($person-getPrefix());echo($person-getGivenName());?做个好邻居在构建类时,它应当正确地处理自己的错误。如果该类不知道如何处理错误,则应当以其调用者理解的格式封装这些错误。此外,避免返回空对象或者状态无效的对象。许多时候,只需通过检验参数并抛出特定异常说明提供参数无效的原因就可以实现这一点。在您养成这个习惯时,它可以帮您—和维护代码或使用对象的人员—节省很多时间。坏习惯:不处理错误考虑清单4中所示的示例,该示例将接受一些参数并返回填充了一些值的Person对象。但是,在parsePersonName()方法中,没有验证提供的$val变量是否为空、是否是零长度字符串或者字符串是否使用无法解析的格式。parsePersonName()方法不返回Person对象,但是返回null。使用这种方法的管理员或程序员可能会觉得很麻烦—至少他们现在需要开始设置断点并调试PHP脚本。清单4.不抛出或处理错误的坏习惯classPersonUtils{publicstaticfunctionparsePersonName($format,$val){if(strpos(,,$val)0){$person=newPerson();$parts=split(,,$val);//Assumethevalueislast,first$person-setGivenName($parts[1]);$person-setFamilyName($parts[0]);}return$person;}}清单4中的parsePersonName()方法可以修改为在if条件外部初始化Person对象,确保总是获得有效的Person对象。但是,您得到的是没有set属性的Person,这仍然没有很好地改善您的困境。好习惯:每个模块都处理自己的错误不要让调用方凭空猜测,而是对参数进行预先验证。如果未设置的变量无法生成有效的结果,请检查变量并抛出InvalidArgumentException。如果字符串不能为空或者必须为特定格式,请检查格式并抛出异常。清单5解释了如何在演示一些基本验证的parsePerson()方法中创建异常以及一些新条件。清单5.抛出错误的好习惯?phpclassInvalidPersonNameFormatExceptionextendsLogicException{}classPersonUtils{publicstaticfunctionparsePersonName($format,$val){if(!$format){thrownewInvalidPersonNameFormatException(InvalidPersonNameformat.);}if((!isset($val))||strlen($val)==0){thrownewInvalidArgumentException(Mustsupplyanon-nullvaluetoparse.);}}}?最终目的是希望人们能够使用您的类,而不必了解其中的工作原理。如果他们使用的方法不正确或者不是按照期望的方法使用,也不需要猜测不能工作的原因。作为一个好邻居,您需要知道对您的类进行重用的人并没有特异功能,因此您需要解决猜测的问题。回页首避免看到美杜莎在我最初了解OO概念时,我十分怀疑接口是否真正有帮助。我的同事给我打了个比方,说不使用接口就好像看到美杜莎的头。在希腊神话中,美杜莎是长着蛇发的女怪。凡是看了她一眼的人都会变成石头。杀死美杜莎的珀尔休斯通过在盾上观察她的影子,避免了变成石头而得以与她对抗。接口就是对付美杜莎的镜子。当您使用一个特定的具体实现时,代码也必须随着实现代码的更改而更改。直接使用实现将限制您的选择,因为您已经在本质上把类变成了“石头”。坏习惯:不使用接口清单6显示了从数据库中装入Person对象的示例。它将获取人员的姓名并返回数据库中匹配的Person对象。清单6.不使用接口的坏习惯?phpclassDBPersonProvider{publicfunctiongetPerson($givenName,$familyName){/*gotothedatabase,gettheperson...*/$person=newPerson();$person-setPrefix(Mr.);$person-setGivenName(John);return$person;}}/*Ineedtogetpersondata...

1 / 22
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功