baik hati
Gunakan lebih sedikit warisan dan lebih banyak kombinasi
Sama seperti Geng Seperti yang dinyatakan sebelum ini dalam Corak Reka Bentuk oleh Empat, kita harus cuba mengutamakan komposisi daripada warisan. Terdapat banyak faedah untuk menggunakan kedua-dua warisan dan komposisi. Perkara utama garis panduan ini ialah apabila anda secara naluri menggunakan warisan, cuba fikirkan sama ada komposisi mungkin memodelkan keperluan anda dengan lebih baik. Dalam sesetengah kes, ini adalah benar. Perkara seterusnya yang mungkin anda fikirkan ialah, "Jadi bilakah saya harus menggunakan warisan?" Jawapannya bergantung pada soalan anda, tetapi berikut adalah beberapa arahan apabila warisan lebih baik daripada komposisi:
Warisan anda menyatakan "Ya" a" bukannya "mempunyai hubungan" (manusia -> haiwan, pengguna -> butiran pengguna) Anda boleh menggunakan semula kod kelas asas (manusia boleh bergerak seperti haiwan)
Anda ingin mengubah suai kelas asas untuk semua kelas Terbitan buat pengubahsuaian global (ubah suai penggunaan tenaga haiwan apabila mereka bergerak)
Buruk: class Employee
{
private $name;
private $email;
public function __construct(string $name, string $email)
{
$this->name = $name;
$this->email = $email;
}
// ...
}
// 不好,因为 Employees "有" taxdata
// 而 EmployeeTaxData 不是 Employee 类型的
class EmployeeTaxData extends Employee
{
private $ssn;
private $salary;
public function __construct(string $name, string $email, string $ssn, string $salary)
{
parent::__construct($name, $email);
$this->ssn = $ssn;
$this->salary = $salary;
}
// ...
}
Baik:
class EmployeeTaxData { private $ssn; private $salary; public function __construct(string $ssn, string $salary) { $this->ssn = $ssn; $this->salary = $salary; } // ... } class Employee { private $name; private $email; private $taxData; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } public function setTaxData(string $ssn, string $salary) { $this->taxData = new EmployeeTaxData($ssn, $salary); } // ... }
2. Elakkan antara muka lancar ialah corak reka bentuk API yang direka untuk meningkatkan kebolehbacaan kod dalam pengaturcaraan berorientasikan objek Ia berdasarkan kaedah rantaian
3 Sukar untuk melakukan
5. Untuk mengetahui lebih lanjut, sila baca Mengapa antara muka yang koheren buruk, oleh Marco Pivetta.
Buruk: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();
Baik:Fluent interface
是一种 旨在提高面向对象编程时代码可读性的API设计模式,他基于方法链Method chaining
有上下文的地方可以降低代码复杂度,例如PHPUnit Mock Builder 和Doctrine Query Builder ,更多的情况会带来较大代价:
While there can be some contexts, frequently builder objects, where this pattern reduces the verbosity of the code (for example the PHPUnit Mock Builder or the Doctrine Query Builder), more often it comes at some costs:
1. 破坏了 对象封装
2. 破坏了 装饰器模式
3. 在测试组件中不好做mock
4. 导致提交的diff
不好阅读
5. 了解更多请阅读 连贯接口为什么不好 ,作者 Marco Pivetta.
坏:
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();
好:
final class Car { private $color; public function __construct($color) { $this->color = $color; } /** * @return string The color of the vehicle */ public function getColor() { return $this->color; } }
3. 推荐使用 final 类
能用时尽量使用 final
interface Vehicle { /** * @return string The color of the vehicle */ public function getColor(); } final class Car implements Vehicle { private $color; public function __construct($color) { $this->color = $color; } /** * {@inheritdoc} */ public function getColor() { return $this->color; } }. Adalah disyorkan untuk menggunakan kelas akhirGunakan kata kunci
4. Galakkan pembangun menggunakan kaedah awam anda dan bukannya mendapatkan akses kepada kaedah yang dilindungi melalui kelas yang diwarisi.
5 Jadikan kelas anda boleh digunakan tanpa melanggar aplikasi Satu-satunya syarat ialah kelas anda harus melaksanakan antara muka dan bukan yang lain kaedah awam ditakrifkan.
Untuk maklumat lanjut, anda boleh membaca catatan blog mengenai topik ini yang ditulis oleh Marco Pivetta (Ocramius
Bad:
rrreeeBaik:
rrreee).