使用组合而不是继承
“Gang of Four”在设计模式里所声明的,你应该优先选择“组合模式”而不是“继承”
译者注:Gang of Four 译成 四人帮,指代 DesignPatternBook 的四位作者
不论是使用“组合模式”还是使用“继承”都有许多理由。
这个话题的要点是当你本能的要使用继承时就想一想是否“组合模式”能帮你更好的解决问题。
你可能会问,“我什么时候应该用继承?”, 这取决于你手头的问题。这里有一个列表说明什么时候使用继承会更合适:
- 你的继承表达了一个“is-a(是)” 的关系,不是“has-a(有)”的关系(对比人类 -> 动物 和 用户-> 用户详情 )
- 你能从基础类中复用代码(人类能够像所有动物一样移动)
- 你想通过修改全局类来对所有派生类进行修改。(例如改变所有动物移动消耗的热量)
不好的:
class Employee
{
private $name;
private $email;
public function __construct($name, $email)
{
$this->name = $name;
$this->email = $email;
}
// ...
}
// 不好,因为是雇员有税收数据
// 税收数据不是一种雇员,所以使用继承不适合
class EmployeeTaxData extends Employee
{
private $ssn;
private $salary;
public function __construct($name, $email, $ssn, $salary)
{
parent::__construct($name, $email);
$this->ssn = $ssn;
$this->salary = $salary;
}
// ...
}
好的:
class EmployeeTaxData
{
private $ssn;
private $salary;
public function __construct($ssn, $salary)
{
$this->ssn = $ssn;
$this->salary = $salary;
}
// ...
}
class Employee
{
private $name;
private $email;
private $taxData;
public function __construct($name, $email)
{
$this->name = $name;
$this->email = $email;
}
public function setTaxData($ssn, $salary)
{
$this->taxData = new EmployeeTaxData($ssn, $salary);
}
// ...
}
避免使用流式接口(fluent interfaces)
fluent interfaces 是一种面向对象的接口,通过Method chaining(链式操作)来提高代码的可读性。
然而有一些Context,通常是构建对象,这个设计模式虽然减少了代码的啰嗦(例如:PHPUnit Mock Builder 或者 Doctrine Query Builder),大部分时候他会产生如下这些消耗:
- 破坏了封装Encapsulation
- 破坏了装饰器 Decorators
- 难以Mock 一个测试套件
- 使 commit 之间的变更难以阅读
想获取更多信息请阅读,请阅读 Marco Pivetta关于这个话题的完整文章
不好的:
class Car
{
private $make = 'Honda';
private $model = 'Accord';
private $color = 'white';
public function setMake(string $make): self
{
$this->make = $make;
// NOTE: Returning this for chaining
return $this;
}
public function setModel(string $model): self
{
$this->model = $model;
// NOTE: Returning this for chaining
return $this;
}
public function setColor(string $color): self
{
$this->color = $color;
// NOTE: Returning this for chaining
return $this;
}
public function dump(): void
{
var_dump($this->make, $this->model, $this->color);
}
}
$car = (new Car())
->setColor('pink')
->setMake('Ford')
->setModel('F-150')
->dump();
好的:
class Car
{
private $make = 'Honda';
private $model = 'Accord';
private $color = 'white';
public function setMake(string $make): void
{
$this->make = $make;
}
public function setModel(string $model): void
{
$this->model = $model;
}
public function setColor(string $color): void
{
$this->color = $color;
}
public function dump(): void
{
var_dump($this->make, $this->model, $this->color);
}
}
$car = new Car();
$car->setColor('pink');
$car->setMake('Ford');
$car->setModel('F-150');
$car->dump();
转载请注明:大后端 » PHP 代码简洁之道——类部分