<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Laravel核心內(nèi)容:契約,你了解多少?

          共 3784字,需瀏覽 8分鐘

           ·

          2021-06-24 13:34

          接口如同契約。接口并不包含任何代碼實(shí)現(xiàn),只是定義了一個(gè)實(shí)現(xiàn)該接口的對(duì)象必須實(shí)現(xiàn)的一系列方法。


          如果一個(gè)對(duì)象實(shí)現(xiàn)了一個(gè)接口,那么我們就能保證這個(gè)接口所定義的一系列方法都能在這個(gè)對(duì)象上調(diào)用。


          由于有接口契約保證特定方法的實(shí)現(xiàn),通過多態(tài)也能使類型安全的語言變得更靈活。

          關(guān)于多態(tài):多態(tài)含義很廣,從本質(zhì)上說,是一個(gè)實(shí)體擁有多種形式。在本書中,我們講多態(tài)說的是一個(gè)接口有多鐘實(shí)現(xiàn)方式。例如,UserRepositoryInterface 可以有 MySQL 和 Redis 兩種實(shí)現(xiàn),并且每一種實(shí)現(xiàn)都是 UserRepositoryInterface 的一個(gè)實(shí)例。


          為了說明接口在強(qiáng)類型語言中的靈活性,我們們來寫一個(gè)簡單的酒店客房預(yù)訂代碼??紤]以下接口:(代碼可滑動(dòng)查看)

          interface ProviderInterface
          {
              public function getLowestPrice($location);
              public function book($location);
          }


          當(dāng)用戶預(yù)訂房間時(shí),我們需要將此事記錄在系統(tǒng)里。所以在 User 類里添加如下方法:(代碼可滑動(dòng)查看)

          class User
          {
              public function bookLocation(ProviderInterface $provider, $location)
              
          {
                  $amountCharged = $provider->book($location);
                  $this->logBookedLocation($location, $amountCharged);
              }
          }


          由于我們對(duì) $provider 做了類型約束,在 User 類的 bookLocation 方法中,就可以放心大膽的認(rèn)為 $provider 實(shí)例上的 book 方法是可以調(diào)用的。


          這給我們復(fù)用 bookLocation 方法帶來了靈活性,完全不必關(guān)心用戶傾向哪家酒店提供商。最后,我們編寫一些代碼來體驗(yàn)下這種靈活性:(代碼可滑動(dòng)查看)

          $location = '希爾頓, 達(dá)拉斯';

          $cheapestProvider = $this->findCheapest($location, array(
              new PricelineProvider,
              new OrbitzProvider,
          ));

          $user->bookLocation($cheapestProvider, $location);


          不管哪家酒店是最便宜的,我們都能夠?qū)⑺鼈魅?nbsp;User 對(duì)象來預(yù)訂房間了。由于 User 對(duì)象只需要有一個(gè)遵從 ProviderInterface 契約的對(duì)象實(shí)例就可以了,所以未來如果有新的酒店供應(yīng)商,我們的代碼也可以很好的工作。

          忘掉細(xì)節(jié):記住,接口實(shí)際上并不做任何事情。它只是簡單的定義了實(shí)現(xiàn)類必須擁有的一系列方法。


          構(gòu)建大型應(yīng)用

          當(dāng)你的團(tuán)隊(duì)在構(gòu)建大型應(yīng)用時(shí),不同的功能模塊往往有著不同的開發(fā)進(jìn)度。例如,一個(gè)開發(fā)人員在開發(fā)數(shù)據(jù)層,另一個(gè)開發(fā)人員在做前端和控制器層。前端開發(fā)者想要測試他的控制器,但是后端開發(fā)進(jìn)度比較慢,無法聯(lián)調(diào)。


          如果這兩個(gè)開發(fā)者能以接口或契約的方式達(dá)成協(xié)議,然后后端開發(fā)的所有類都遵循這種協(xié)議,就像下面這段代碼:(代碼可滑動(dòng)查看)

          interface OrderRepositoryInterface 
          {
              public function getMostRecent(User $user);
          }


          一旦建立了契約,就算契約還沒有真正實(shí)現(xiàn),前端開發(fā)者也可以測試他的控制器了!這樣一來,應(yīng)用中的不同組件就可以按不同的速度開發(fā),同時(shí)仍然允許編寫適當(dāng)?shù)膯卧獪y試。


          此外,這種方式還可以使組件內(nèi)部的改動(dòng)不會(huì)影響到其它不相關(guān)的組件。要始終牢記「無知是?!埂N覀儾幌胱岊愔酪蕾囀侨绾喂ぷ鞯?,只需要知道它們能做什么。所以,先定義好契約,再來寫控制器:(代碼可滑動(dòng)查看)

          class OrderController {
              public function __construct(OrderRepositoryInterface $orders)
              
          {
                  $this->orders = $orders;
              }
              public function getRecent()
              
          {
                  $recent = $this->orders->getMostRecent(Auth::user());
                  return View::make('orders.recent', compact('recent'));
              }
          }


          前端開發(fā)者甚至可以為這接口寫個(gè)「假」實(shí)現(xiàn),然后這個(gè)應(yīng)用的視圖就可以用假數(shù)據(jù)渲染了:(代碼可滑動(dòng)查看)

          class DummyOrderRepository implements OrderRepositoryInterface 
          {
              public function getMostRecent(User $user)
              
          {
                  return array('Order 1''Order 2''Order 3');
              }
          }


          編寫好假實(shí)現(xiàn)之后,就可以在服務(wù)容器里將其綁定到契約上,然后在整個(gè)應(yīng)用中都可以調(diào)用它了:(代碼可滑動(dòng)查看)

          $this->app->bind(OrderRepositoryInterface::class, function ($app) {
              return new DummyOrderRepository();
          });


          接下來,如果后臺(tái)開發(fā)者寫完了真正的實(shí)現(xiàn)代碼,如RedisOrderRepository。服務(wù)容器中的綁定可以輕松切換到新的實(shí)現(xiàn),整個(gè)應(yīng)用將會(huì)使用開始從 Redis 讀取出來的訂單數(shù)據(jù)。


          接口即綱領(lǐng):接口有助于開發(fā)應(yīng)用所提供的、已定義好的功能「框架」。 在組件的設(shè)計(jì)階段,團(tuán)隊(duì)里使用接口進(jìn)行討論是很方便的,例如,定義一個(gè) BillingNotifierInterface 接口,然后討論它提供哪些方法。在編寫任何實(shí)現(xiàn)代碼前,最好先通過接口討論達(dá)成一致,這是構(gòu)建一套好 API 的必要前提!


          有一款不錯(cuò)的開源電商系統(tǒng)likeshop,給大家推薦一下,可以下載免費(fèi)商用或者學(xué)習(xí)借鑒思路,地址:  https://gitee-github.com/VyN8svYL

          瀏覽 105
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色一级小说在线观看 | 国产黄色影片免费 | 老司机在线无码视频免费 | 豆花AV网站在线观看 | 日本中文字幕不卡 |