Structural Patterns
1. Adapter (Ổn định)Giải thích: Mẫu Adapter cho phép bạn chuyển đổi giao diện của một lớp thành một giao diện khác mà các đối tượng khác có thể sử dụng.
Ví dụ:
<?
// Adapter interface
interface MediaPlayer {
public function play($audioType, $fileName);
}
// Existing class with incompatible interface
class Mp3Player {
public function playMp3($fileName) {
echo "Playing MP3 file: $fileName\n";
}
}
// Adapter class
class MediaAdapter implements MediaPlayer {
private $mp3Player;
public function __construct() {
$this->mp3Player = new Mp3Player();
}
public function play($audioType, $fileName) {
if ($audioType == 'mp3') {
$this->mp3Player->playMp3($fileName);
}
}
}
// Client code
$mediaAdapter = new MediaAdapter();
$mediaAdapter->play('mp3', 'song.mp3');
2. Bridge (Cầu)
Giải thích: Mẫu Bridge tách biệt một lớp trừu tượng từ việc triển khai của nó, cho phép chúng hoạt động độc lập với nhau.
Ví dụ PHP:<? // Abstraction
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
abstract public function draw();
}
// Implementor
interface DrawAPI {
public function drawCircle($radius, $x, $y);
}
// Concrete Implementor
class RedCircle implements DrawAPI {
public function drawCircle($radius, $x, $y) {
echo "Drawing a red circle at ($x, $y) with radius $radius\n";
}
}
// Refined Abstraction
class Circle extends Shape {
private $x, $y, $radius;
public function __construct($x, $y, $radius, $color, DrawAPI $drawAPI) {
parent::__construct($color);
$this->x = $x;
$this->y = $y;
$this->radius = $radius;
$this->drawAPI = $drawAPI;
}
public function draw() {
$this->drawAPI->drawCircle($this->radius, $this->x, $this->y);
}
}
// Client code
$redCircle = new Circle(100, 100, 10, 'red', new RedCircle());
$redCircle->draw();
3. Composite (Tổ hợp)
Giải thích: Mẫu Composite cho phép bạn xây dựng cấu trúc cây đối tượng dạng cây để biểu diễn các mối quan hệ phân cấp giữa các đối tượng.
Ví dụ PHP:
Ví dụ PHP:
<? // Abstraction
// Component
interface Employee {
public function showDetails();
}
// Leaf
class Developer implements Employee {
private $name;
private $position;
public function __construct($name, $position) {
$this->name = $name;
$this->position = $position;
}
public function showDetails() {
echo "Developer: $this->name, Position: $this->position\n";
}
}
// Composite
class Manager implements Employee {
private $name;
private $position;
private $subordinates = [];
public function __construct($name, $position) {
$this->name = $name;
$this->position = $position;
}
public function add(Employee $employee) {
$this->subordinates[] = $employee;
}
public function showDetails() {
echo "Manager: $this->name, Position: $this->position\n";
foreach ($this->subordinates as $subordinate) {
$subordinate->showDetails();
}
}
}
// Client code
$developer1 = new Developer('Alice', 'Front-end Developer');
$developer2 = new Developer('Bob', 'Back-end Developer');
$manager = new Manager('Charlie', 'Project Manager');
$manager->add($developer1);
$manager->add($developer2);
$manager->showDetails();
4. Decorator (Trang trí)
Giải thích: Mẫu Decorator cho phép bạn thêm chức năng mới cho đối tượng mà không cần sửa đổi mã nguồn gốc của nó.
Ví dụ PHP:
Ví dụ PHP:
<? // Component
interface Coffee {
public function cost();
}
// Concrete Component
class SimpleCoffee implements Coffee {
public function cost() {
return 5; // Giá cà phê đơn giản
}
}
// Decorator
abstract class CoffeeDecorator implements Coffee {
protected $coffee;
public function __construct(Coffee $coffee) {
$this->coffee = $coffee;
}
public function cost() {
return $this->coffee->cost();
}
}
// Concrete Decorator
class MilkDecorator extends CoffeeDecorator {
public function cost() {
return parent::cost() + 2; // Cộng thêm giá sữa
}
}
// Concrete Decorator
class SugarDecorator extends CoffeeDecorator {
public function cost() {
return parent::cost() + 1; // Cộng thêm giá đường
}
}
// Client code
$coffee = new SimpleCoffee();
$coffeeWithMilk = new MilkDecorator($coffee);
$coffeeWithMilkAndSugar = new SugarDecorator($coffeeWithMilk);
echo "Cost of simple coffee: {$coffee->cost()} USD\n";
echo "Cost of coffee with milk: {$coffeeWithMilk->cost()} USD\n";
echo "Cost of coffee with milk and sugar: {$coffeeWithMilkAndSugar->cost()} USD\n";
5. Facade (Gương mặt)
Giải thích:
Mẫu Facade cung cấp một giao diện đơn giản cho một hệ thống phức tạp, giúp che đi sự phức tạp và tạo điểm truy cập dễ dàng cho client.
Ví dụ PHP:
6. Flyweight (Nhẹ)
Ví dụ PHP:
<?
// Subsystem
class CPU {
public function freeze() { echo "CPU freeze\n"; }
public function jump($address) { echo "CPU jump to $address\n"; }
public function execute() { echo "CPU execute\n"; }
}
class Memory {
public function load($position, $data) { echo "Memory load data into position $position: $data\n"; }
}
class HardDrive {
public function read($sector, $size) { echo "Hard Drive read sector $sector with size $size\n"; }
}
// Facade
class ComputerFacade {
private $cpu;
private $memory;
private $hardDrive;
public function __construct() {
$this->cpu = new CPU();
$this->memory = new Memory();
$this->hardDrive = new HardDrive();
}
public function start() {
$this->cpu->freeze();
$this->memory->load(0, 'Boot data');
$this->cpu->jump(1);
$this->cpu->execute();
}
}
// Client code
$computer = new ComputerFacade();
$computer->start();
6. Flyweight (Nhẹ)
Giải thích: Mẫu Flyweight giúp bạn chia sẻ thông tin chung giữa nhiều đối tượng để giảm bộ nhớ hoặc tối ưu hóa hiệu suất.
Ví dụ PHP:
Ví dụ PHP:
<?
// Flyweight interface
interface Coffee {
public function serve();
}
// Concrete Flyweight
class Espresso implements Coffee {
public function serve() {
return "Espresso";
}
}
// Flyweight Factory
class CoffeeFactory {
private $coffeeTypes = [];
public function getCoffee($type) {
if (!isset($this->coffeeTypes[$type])) {
$this->coffeeTypes[$type] = new $type();
}
return $this->coffeeTypes[$type];
}
}
// Client code
$factory = new CoffeeFactory();
$espresso1 = $factory->getCoffee('Espresso');
$espresso2 = $factory->getCoffee('Espresso');
echo $espresso1->serve() . " is the same as " . $espresso2->serve() . "\n";
7. Proxy (Ủy quyền)
Giải thích: Mẫu Proxy cho phép bạn cung cấp một đối tượng đại diện để kiểm soát quyền truy cập đối tượng gốc hoặc thực hiện các hành động bổ sung trước hoặc sau khi gọi phương thức của đối tượng gốc.
Ví dụ PHP:
Ví dụ PHP:
<?
// Subject
interface Image {
public function display();
}
// Real Subject
class RealImage implements Image {
private $filename;
public function __construct($filename) {
$this->filename = $filename;
$this->loadImage();
}
private function loadImage() {
echo "Loading image: $this->filename\n";
}
public function display() {
echo "Displaying image: $this->filename\n";
}
}
// Proxy
class ProxyImage implements Image {
private $realImage;
private $filename;
public function __construct($filename) {
$this->filename = $filename;
}
public function display() {
if ($this->realImage === null) {
$this->realImage = new RealImage($this->filename);
}
$this->realImage->display();
}
}
// Client code
$image1 = new ProxyImage('image1.jpg');
$image2 = new ProxyImage('image2.jpg');
// Image1 will be loaded and displayed, Image2 will only be loaded and displayed when needed.
$image1->display();
$image2->display();