PHP设计模式(六):MVC

原文地址:PHP设计模式(六):MVCphp

Introduction

20世纪80年代,计算机发展迅速,编程技术也日益分化。桌面应用编程,也逐渐出现了用户图形界面和程序逻辑分离的程序设计。到了90年代,web的出现更是让这种程序设计模式得以延续。
这种设计模式即是MVC(Model-View-Control),除了MVC,还有MVC的变种,如MVVM(Model-View-View Model)等。程序员

MVC

回到80年代的桌面应用编程,当时面向对象的编程设计模式(见PHP设计模式(一):基础编程模式)兴起,程序员将桌面应用分割成两个大的对象:领域对象(domain objects)和可视对象(presentation objects)。领域对象是对现实事物的抽象模型,可视对象是对用户界面部分的抽象模型。
后来人们发现,只有领域对象和可视对象是不够的,特别是在复杂的业务中。根据PHP设计模式(三):封装中介绍的设计原则,在面向对象程序设计中,类和类之间的访问、交互和更新应该是经过Accessors和Mutators。
那么若是操做领域对象呢?人们引入了控制器(controller)的对象,经过控制器来操做领域模型。
到此,MVC模型逐渐稳定下来,用户经过可视对象操做控制器对象,控制器对象再去操做领域对象。web

MVC中的设计模式

上面介绍的MVC属于抽象度比较高的设计模式,在实际编程中,须要遵照下面的设计模式。编程

基于接口去编程

基于接口去编程的好处就是分离设计和实现,这一点咱们在PHP设计模式(二):抽象类和接口已经介绍过了,下面咱们举一个实际的例子来讲明这个设计的好处。设计模式

<?php
abstract class Animal {
  protected $name;
  abstract protected function eatFish();
  abstract protected function eatMoss();
  public function eat() {
    if ($this->eatFish()) {
      echo $this->name . " can eat fish.\n";
    }
    if ($this->eatMoss()) {
      echo $this->name . " can eat moss.\n";
    }
  }
}
?>

咱们建立一个鲸鱼类:架构

<?php
include_once('Animal.php');
class Whale extends Animal {
  public function __construct() {
    $this->name = "Whale";
  }
  public function eatFish() {
    return TRUE;
  }
  public function eatMoss() {
    return FALSE;
  }
}

$whale = new Whale();
$whale->eat();
?>

运行一下:dom

$ php Whale.php
Whale eats fish.

看上去没什么问题,对吧?咱们建立一个鲤鱼类:this

<?php
include_once('Animal.php');
class Carp extends Animal {
  public function __construct() {
    $this->name = "Carp";
  }
  public function eatMoss() {
    return TRUE;
  }
}

$carp = new Carp();
$carp->eat();
?>

运行一下:架构设计

$ php Carp.php
PHP Fatal error: Class Carp contains 1 abstract method and must therefore be
declared abstract or implement the remaining method (Animal::eatFish) in
Carp.php on line 9

报错了,对吧?由于咱们实现Carp.php的时候故意没有去实现eatFish接口,基于接口的编程设计模式能够在开发期就发现这种逻辑错误。设计

使用组件而不是继承

将一个对象拆成更小的对象,这些小的对象成为组件(composition)。尽可能使用组件而不是继承的设计模式的意义在于,多种继承之下,子类可能会拥有大量毫无心义的未实现方法。而经过组件的方式,子类能够选择须要的组件。
下面给出一个例子:

<?php
abstract class Animal {
  protected $name;
  abstract protected function eatFish();
  abstract protected function eatMoss();
  public function eat() {
    if ($this->eatFish()) {
      echo $this->name . " can eat fish.\n";
    }
    if ($this->eatMoss()) {
      echo $this->name . " can eat moss.\n";
    }
  }
}

class Whale extends Animal {
  protected function __construct() {
    $this->name = "Whale";
  }
  protected function eatFish() {
    return TRUE;
  }
  protected function eatMoss() {
    return FALSE;
  }
}

class BullWhale extends Whale {
  public function __construct() {
    $this->name = "Bull Whale";
  }
  public function getGender() {
    return "Male";
  }
}
?>

这里的BullWhale其实很是冗余,实际的业务模型可能并不须要这么复杂,这就是多重继承的恶果。
而组件则不一样,经过将行为拆分红不一样的部分,又最终子类决定使用哪些组件。
下面给出一个例子:

<?php
class Action {
  private $name;
  public function __construct($name) {
    $this->name = $name;
  }
  public function eat($food) {
    echo $this->name . " eat ". $food . ".\n";
  }
}

class Gender {
  private $gender;
  public function __construct($gender) {
    $this->gender= $gender;
  }
  public function getGender() {
    return $this->gender;
  }
}

class BullWhale {
  private $action;
  private $gender;
  public function __construct() {
    $this->action = new Action("Bull Whale");
    $this->gender = new Gender("Male");
  }
  public function eatFood($food) {
    $this->action->eat($food);
  }
  public function getGender() {
    return $this->gender->getGender();
  }
}

$bullWhale = new BullWhale();
$bullWhale->eatFood("fish");
echo $bullWhale->getGender() . "\n";
?>

运行一下:

$ php BullWhale.php
Bill Whale eat fish.
Male

BullWhale由Action和Gender组件构成,不一样的类能够选择不一样的组件组合,这样就不会形成类冗余了。

Summary

实际编程中,更多的每每是混合架构,如既包含继承,又包含组件的编程设计模式。不过,掌握基本的编程架构设计是一切的基础。

相关文章
相关标签/搜索