重庆小潘seo博客

当前位置:首页 > 重庆网站建设 >

重庆网站建设

PHP开发:从程序化到面向对象编程

时间:2016-08-27 09:17:50 作者:采集侠 来源:网络整理
这份教程的诞生源自一年多之前Robert C.Martin在演讲中带给我的启发。当时他的演讲主题在于讨论创造终极编程语言的可能性。在过程中,他提出了这样几个问题:为什么会存在终极编程语言?这样的语言应具备哪些特性?但随着他的讲解,我从中发现另一种有趣的

      $this->businessLogic->getEventById(  

   foreach (retrieveEvents($client, $_GET['showThisCalendar']) as $event) {  

[...]  

简单来说,这意味着具体实施应依赖于抽象类。类越趋近抽象,它们就越不容易发生改变。因此我们可以这样理解:变更频繁的类应依赖于其它更为稳定的类。所以任何应用中最不稳定的部分很可能是用户界面,这在我们的应用示例中通过Presenter类来实现。让我们再来明确一下依赖倒置流程。

         return;  

这个例子恐怕要算我们此次编写的代码中最为复杂的函数。它所调用的是名为putTitle()的辅助函数,其作用是将某些经过格式调整的HTML输出以充当标题。标题中将包含我们日程表的实际名称,这是通过调用来自functions_google_api.php文件中的getCalendar()函数来实现的。返回的日历信息是一个数组,其中包含一个summary字段,而这正是我们要找的内容。

   

      print('<br>');  

\

      $this->businessLogic = new Logic();  

   private $presenter;  

\

接下来,我们将使用Presenter中的printCalendarContents()方法,如下所示:

然而仅仅消除函数指针还远远不够。面向对象的编程机制必然带来替代方案,事实也确实如此,它包含着多态特性与一套简单语法。重点来了,多态性正是面向对象编程的核心价值,即:控制流与源代码在依赖关系上正好相反。

红色线条则引入了完全不同的概念,它们代表着最初的源代码依赖关系。之所以说“最初”,是因为随着应用的运行其指向将变得愈发复杂、难以把握。putMenu()方法中包含着被特定关系所调用的函数的名称。这是一种依赖关系,同时也是适用于所有其它关系创建方法的基本规则。它们的具体关系取决于其它函数的行为。

   global $client;  

   return getEventList($client, htmlspecialchars($_GET['showThisCalendar']))['items'];  

require_once __DIR__ . '/../apiAccess.php';  

摆脱全局变量

谷歌专门针对PHP提供一套API客户端,我们将利用它与自己的谷歌账户进行对接,从而对日程表服务加以操作。要想让代码正确起效,大家需要通过设定让自己的谷歌账户接受来自日程表的查询。

   

   putMenu();  

\

• functions_google_api.php – 囊括所有前面提到的谷歌API。

$client = createClient();  

   

         return;  

function printCalendarContents($client) {  

试手任务

   

[...]  

(new Router($presenter))->doUserAction();  

   global $client;  

   print('<div display="block">'.$text.'</div>');  

}  

function printMenu() {  

对于当前代码我们可以绘制出一份关系图,内容如下所示。通过这幅关系图,我们可以看到应用程序运行流程的前几个步骤。当然,把整套流程都画下来就太过复杂了。

   }  

      $this->putCalendarListElement($calendar);  

   

function isCurrentEvent($event) {  

}  

现在惟一漏网的潜在设计缺陷就只剩下$client全局变量了。应用程序中的所有代码都会对其进行访问,但与之形成鲜明对比的是,真正有必要访问$client的只有Logic类一个。最直观的解决办法肯定是使其变更为专用类变量,但这样一来我们就需要将$client经由Router传递至Presenter处,从而使presenter能够利用$client变更创建出Logic对象——这对于解决问题显然无甚作用。我们的设计初衷是在独立环境下建立类,并准确为其分配依赖关系。

         putBlock('This event has status ' . $event['status']);  

   foreach ($this->businessLogic->getEventsForCalendar() as $event) {  

以上变更完成之后,点击Show Calendars,屏幕上会出现错误提示。由于我们链接内部的所有行为都指向Logic类中的函数名称,因此必须通过更多一致性调整来恢复二者之间的依赖关系。下面我们对方法进行一一修改,先来看第一条错误信息:

恢复源代码依赖关系

}  

范式局限

}  

         $_GET['showThisEvent'],  

   }  

require_once './Presenter.php';  

B:抽象不应依赖于细节,细节应依赖于抽象。

      (new Presenter())->putMenu();  

如果要为目前的代码绘制依赖关系类图,则应如下所示:

   putLink('?action=printCalendars', 'Show Calendars');  

function foo() {  

   function doUserAction() {  

$function();        // Goes into foo()  

require_once './google-api-php-client/src/Google_Client.php';  

if(!authenticate($client)) return;  

   $eventsForCalendar = $this->businessLogic->getEventsForCalendar(htmlspecialchars($_GET['showThisCalendar']));  

}  

   foreach (getCalendarList($client)['items'] as $calendar) {  

}  

         ' and last updated at ' .  

function putTitle($text) {  

   

   

   global $client;  

尽管该方法只负责显示信息,但其功能仍需在对$event结构非常了解的前提下方能实现。不过对于我们的简单实例来说,这已经足够了。对于其余方法,大家可以通过类似的方式进行分离。

这里有一项名为doUserAction()的函数,它的生效与否取决于一条很长的if-else声明;其它方法则根据GET变量中的参数决定调用情况。这些方法随后利用API与谷歌日程表对接,并在屏幕上显示出我们需要的任何结果。

         putTitle('Details for event: '. $event['summary']);  

我们当前的代码完全没问题,但我想我们可以通过调整使其以更合适的方式组织起来。大家可能已经从附带的源代码中发现,该项目所有已经组织完成的代码都被命名为“GoogleCalProceduralOrganized”。

因此我们需要保证只有Presenter感知到这一情况,即将以上两个方法变换为下列内容:

对于任何大型类结构,我们都倾向于使用Factories;但在本文的小小范例中,index.php文件已经足以容纳逻辑创建了。作为应用程序的入口点,这个类似于高层体系结构中“main”的文件仍然处于业务逻辑的范畴之外。

   

A:高层模块不应依赖于低级模块,二者都应依赖于抽象。

   $this->putEvent(  

function printCalendarContents() {  

function getEventById($eventId, $calendarId) {  

就是这样,我们已经成功完成了依赖倒置。

   

   function putHome() {  

每种编程范式都限制了我们将想象转化为现实的能力。这些范式去掉了一部分可行方案,却纳入另一些方案作为替代,但这一切都是为了实现同样的表示效果。模块化编程令程序规模受到制约,强迫程序员只能在对应模块范畴之内施展拳脚,且每个模块结尾都要以“go-to”来指向其它模块。这种设定直接影响了程序成品的规模。另外,结构化编程与程序化编程方式去掉了“go-to”声明,从而限制了程序员对序列、选择以及迭代语句的调整能力。序列属于变量赋值,选择属于if-else判断,而迭代则属于do-while循环。这些已经成为当下编程语言与范式的构建基石。

   putLink('?home', 'Home');  

   }  

其余部分代码与我们之前讨论过的内容相近,甚至更容易理解。大家可以抱着轻松的心情随便看看,然后抖擞精神进军下一章。

}  

\