Skip to content

Instantly share code, notes, and snippets.

@andreconghau
Created June 30, 2022 04:55
Show Gist options
  • Save andreconghau/ff2240705e679c8d7473a45795f68480 to your computer and use it in GitHub Desktop.
Save andreconghau/ff2240705e679c8d7473a45795f68480 to your computer and use it in GitHub Desktop.
<?php
/**
* https://www.youtube.com/watch?v=IoLXT1UleX4&index=7&list=PLGJDCzBP5j3xGaW0AGlaVHK2TMEr2XkP9
* https://github.com/ezimuel/PHP-design-patterns
* http://fsd14.com/post/91-design-pattern-decorator-design
*
*
* Chúng ta có thể sử dụng decorator pattern khi ta muốn đưa ra một số trách nhiệm bổ sung vào class cơ sở. Nghĩa là một class có thể
* được add thêm một chức năng của class khác mà không thay đổi cấu trúc của class.
*
* Design pattern này là một sự thay thế tuyệt vời cho tính năng sub-classing để mở rộng các chức năng với một số lợi ích được bổ sung.
*
* Với mỗi ứng dụng, chúng ta cần một vài kiểu thay đổi và/hoặc hoàn thiện nó tại những khoảng thời gian đồng nhất.
* Vì vậy, trong trường hợp này chúng ta có thể thực hiện decorator design pattern, cuối cùng code của chúng ta sẽ
* được cải thiện về chất lượng và tăng khả năng mở rộng của nó.
*
*/
/**
* Vấn đề:
* Khi chúng ta thực hiện chức năng soạn nội dung mail. Thường chúng ta sẽ tạo 1 class với đầy đủ header, body, footer.
* Khi cần thay đổi nôi dung mail thường thi chúng ta sẽ tạo một class khác đẻ kế thừa và override lai ví dụ như Class christmasEmail
* Khi tới một sự kiện khác như Happy New Year chúng ta lại cần một nôi dung mail mới và ta làm điều tương tự với newYearEmail
* Vấn đề sẽ xảy ra khi ta cần gửi cả 2 nôi dung trong 1 mail.
*/
class eMailBody
{
private $header = 'This is email header';
private $footer = 'This is email Footer';
public $body = '';
public function loadBody()
{
$this->body .= "This is Main Email body.<br />";
}
}
class christmasEmail extends eMailBody
{
public function loadBody()
{
parent::loadBody();
$this->body .= "Added Content for Xmas<br />";
}
}
$christmasEmail = new christmasEmail();
$christmasEmail->loadBody();
echo $christmasEmail->body;
print '<hr>';
class newYearEmail extends eMailBody
{
public function loadBody()
{
parent::loadBody();
$this->body .= "Added Content for New Year<br />";
}
}
$newYearEmail = new newYearEmail();
$newYearEmail->loadBody();
echo $newYearEmail->body;
print '<hr>';
print '<p>Decorator Pattern</p>';
print '<hr>';
/**
* Giải pháp:
* Decorator pattern (còn được gọi là Wrapper)
* là một design pattern cho phép các hành vi được thêm vào một đối tượng cụ thể, tĩnh hoặc động,
* mà không ảnh hưởng đến các hành vi của các đối tượng khác trong cùng một class.
*/
interface eMailBodyDeco
{
public function loadBody();
}
/**
* Class eMail
* Main class: Đây là class chính nơi tạo ra default body của một email, cái mà tôi thường sử dụng để gửi email.
*/
class eMailDeco implements eMailBodyDeco
{
public function loadBody()
{
echo "This is Main Email body.<br />";
}
}
/**
* Class emailBodyDecorator
* Main decorator: Đây là decorator class chính của chúng ta, nó tham chiếu đến email class chính và thay đổi hành vi của mình khi cần thiết.
* Ở đây chúng ta đã định nghĩa một method trừu tượng loadBody mà sub decorator cần thực hiện việc thay đổi hành vi.
*/
abstract class emailBodyDecorator implements eMailBodyDeco
{
protected $emailBody;
public function __construct(eMailBodyDeco $emailBody)
{
$this->emailBody = $emailBody;
}
abstract public function loadBody();
}
/**
* Class christmasEmailBody
* Sub-Deco
*/
class christmasEmailBody extends emailBodyDecorator
{
public function loadBody()
{
echo 'This is Extra Content for Christmas<br />';
$this->emailBody->loadBody();
}
}
/**
* Class newYearEmailBody
* Sub-deco
*/
class newYearEmailBody extends emailBodyDecorator
{
public function loadBody()
{
echo 'This is Extra Content for New Year.<br />';
$this->emailBody->loadBody();
}
}
/**
* CALL DEMO
*/
// Chay binh tnuong.
print '<p><strong>Noi dung binh thuong:</strong></p>';
$email = new eMailDeco();
$email->loadBody();
// noi dung chirstmas.
print '<p><strong>Noi Dung christmas:</strong></p>';
$email = new eMailDeco();
$email = new christmasEmailBody($email);
$email->loadBody();
// Noi Dung happy new year.
print '<p><strong>Noi Dung Happy new year:</strong></p>';
$email = new eMailDeco();
$email = new newYearEmailBody($email);
$email->loadBody();
// Noi Dung ca 3 thong diep.
print '<p><strong>Noi Dung ca 3 thong diep:</strong></p>';
$email = new eMailDeco();
$email = new christmasEmailBody($email);
$email = new newYearEmailBody($email);
$email->loadBody();
print '<hr><p><strong>Cach viet khac:</strong></p>';
/**
* VD 2:
*
*/
class Book
{
private $author;
private $title;
function __construct($title_in, $author_in)
{
$this->author = $author_in;
$this->title = $title_in;
}
function getAuthor()
{
return $this->author;
}
function getTitle()
{
return $this->title;
}
function getAuthorAndTitle()
{
return $this->getTitle() . ' by ' . $this->getAuthor();
}
}
class BookTitleDecorator
{
protected $book;
protected $title;
public function __construct(Book $book_in)
{
$this->book = $book_in;
$this->resetTitle();
}
//doing this so original object is not altered
function resetTitle()
{
$this->title = $this->book->getTitle();
}
function showTitle()
{
return $this->title;
}
}
class BookTitleExclaimDecorator extends BookTitleDecorator
{
private $btd;
public function __construct(BookTitleDecorator $btd_in)
{
$this->btd = $btd_in;
}
function exclaimTitle()
{
$this->btd->title = "!" . $this->btd->title . "!";
}
}
class BookTitleStarDecorator extends BookTitleDecorator
{
private $btd;
public function __construct(BookTitleDecorator $btd_in)
{
$this->btd = $btd_in;
}
function starTitle()
{
$this->btd->title = Str_replace(" ", "*", $this->btd->title);
}
}
writeln('BEGIN TESTING DECORATOR PATTERN');
writeln('');
$patternBook = new Book('Gamma, Helm, Johnson, and Vlissides', 'Design Patterns');
$decorator = new BookTitleDecorator($patternBook);
$starDecorator = new BookTitleStarDecorator($decorator);
$exclaimDecorator = new BookTitleExclaimDecorator($decorator);
writeln('showing title : ');
writeln($decorator->showTitle());
writeln('');
writeln('showing title after two exclaims added : ');
$exclaimDecorator->exclaimTitle();
$exclaimDecorator->exclaimTitle();
writeln($decorator->showTitle());
writeln('');
writeln('showing title after star added : ');
$starDecorator->starTitle();
writeln($decorator->showTitle());
writeln('');
writeln('showing title after reset: ');
writeln($decorator->resetTitle());
writeln($decorator->showTitle());
writeln('');
writeln('END TESTING DECORATOR PATTERN');
function writeln($line_in)
{
echo $line_in . "<br/>";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment