PHP设计模式(三):封装

原文地址:PHP设计模式(三):封装php

Introduction

面向对象编程中,一切都是对象,对一个对象的封装,也成了面向对象编程中必不可少的部分。
和C/C++,Java,Python等语言同样,PHP也支持封装。程序员

封装/Encapsulation

对事物的封装是指,将事物进行抽象后,提供抽象概念的实现的具体方法。编程

听起来很拗口,仍是举鲸鱼的例子。
对于鲸鱼来讲,须要吃东西这个行为,吃自己是一个抽象的概念,由于具体到怎么吃,是咀嚼和消化的过程,甚至如何咀嚼和消化也是不可见的。对外部而言,可见的只是吃这一个接口,如何吃、怎么吃,是被封装在了鲸鱼的实现中。
甚至能够说,消化系统,被封装到了鲸鱼这个对象中,对外部不可见,仅仅鲸鱼本身可见。设计模式

封装方法

和别的程序设计语言同样,PHP也只是三种封装概念:Private,Protected,Public。this

私有/Private

私有的概念是,仅仅对象内部可见,外部不可见,如:设计

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

name是鲸鱼的私有属性,chew()和digest()是鲸鱼的私有方法,对于其余类来讲,都是不可见的。对于现实来讲,咱们若是只是注重吃,并无必要去关心鲸鱼是如何去吃的。code

保护/Protected

保护的概念是,仅仅是自身类和继承类可见,这个关键字的用途主要是防止滥用类的派生,另外三方库编写的时候会用到,防止误用。对象

<?php
abstract class Animal {
  private $name;
  abstract public function eat($food);
  protected function chew($food) {
    echo "Chewing " . $food . "\n";
  }
  protected function digest($food) {
    echo "Digest " . $food . "\n";
  }
}

class Whale extends Animal {
  private $name;
  public function __construct() {
    $this->name = "Whale";
  }
  public function eat($food) {
    chew($food);
    digest($food);
  }
}
?>

鲸鱼类能够经过继承使用动物类的咀嚼和消化方法,可是别的继承鲸鱼类的类就不能够再使用动物类的咀嚼和消化方法了。保护更可能是用于面向对象设计,而不是为了编程来实现某个需求。继承

公共/Public

公共的概念就是,任何类、任何事物均可以访问,没有任何限制,这里再也不赘述。接口

Getters/Setters

Getters和Setters也叫Accessors和Mutators,在Java/C#等语言中常以get()/set()方法出现。
对于这两个东西的争议很大,考虑下面一个类:

<?php
class Price {
  public $priceA;
  public $priceB;
  public $priceC;
  ...
}
?>

若是不使用Getters/Setters,咱们给Price类赋值和取值通常是这样:

<?php
  $price = new Price();
  $price->priceA = 1;
  $price->priceB = 2;
  $price->priceC = 3;
  ...
  echo $price->priceA;
  echo $price->priceB;
  echo $price->priceC;
  ...
?>

可是若是使用了Getters/Setters,Price类将变成这样:

<?php
class Price {
  private $priceA;
  private $priceB;
  private $priceC;
  public function getPriceA() {
    return $this->priceA;
  }
  public function setPriceA($price) {
    $this->priceA = $price;
  }
  ...
}
?>

这时候赋值将变成这样:

<?php
  $price = new Price();
  $price->setpriceA(1);
  $price->setPriceB(2);
  $price->setPriceC(3);
  ...
  echo $price->getPriceA();
  echo $price->getPriceB();
  echo $price->getPriceC();
  ...
?>

是否是感受须要多敲不少代码?这也是不少程序员不肯意使用get/set的缘由,形成了大量的看似无用冗余的代码。
为何叫看似冗余和无用?由于Getters/Setters是编程设计方法,而不是编程实现方法。

在面向对象程序设计中,类和类之间的访问、交互和更新应该是经过Accessors和Mutators,也就是Getters和Setters来实现。直接访问和修改破坏了类的封装性。

为何采用这种设计方式?由于程序设计是对现实问题的抽象,而在编程的工程中程序员扮演的角色每每是上帝。
考虑这样一种场景:你朋友要求你更名,决定是否更名的人是你,而不是你朋友。在你的朋友的视觉(也就是你朋友的类),他不能直接去修改你的名字。
若是你直接采用非Getters/Setters的设计方法,事实上是程序员扮演的这个上帝修改了现实规则,容许你朋友可以随意更改你的姓名,显然这是不合理的。

Summary

合理的封装对于好的程序设计是必不可少的,虽然什么都是Public也能解决编程问题,可是这不是用程序设计解决问题的思路。

相关文章
相关标签/搜索