development:software-architecture:design-patterns:factory
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
development:software-architecture:design-patterns:factory [2024/08/16 02:38] – tungnt | development:software-architecture:design-patterns:factory [2024/08/19 09:29] (current) – tungnt | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Factory ====== | ====== Factory ====== | ||
+ | |||
+ | Trong số những kiểu mẫu thiết kế hay design pattern trong PHP thì Factory là một trong những pattern được sử dụng phổ biến nhất. | ||
===== Simple Factory Pattern ===== | ===== Simple Factory Pattern ===== | ||
+ | **Cách code khi không dùng Factory Pattern:** | ||
+ | |||
+ | <file php> | ||
+ | //... | ||
+ | |||
+ | private function getServiceLogistics($cargoVolume) | ||
+ | { | ||
+ | switch ($cargoVolume) { | ||
+ | case 10: | ||
+ | return [ | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ]; | ||
+ | case 20: | ||
+ | return [ | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | ]; | ||
+ | default: | ||
+ | return []; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | //... | ||
+ | |||
+ | var_dump($this-> | ||
+ | </ | ||
+ | |||
+ | **Cách code khi dùng Simple Factory Pattern:** | ||
+ | |||
+ | <file php> | ||
+ | /** | ||
+ | * ServiceLogistics | ||
+ | */ | ||
+ | class ServiceLogistics{ | ||
+ | private $name; | ||
+ | private $door; | ||
+ | private $price; | ||
+ | | ||
+ | /** | ||
+ | * __construct | ||
+ | * | ||
+ | * @param | ||
+ | * @param | ||
+ | * @param | ||
+ | * @return void | ||
+ | */ | ||
+ | public function __construct($name = "Truck 10", $door = 6, $price = 250000) { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | | ||
+ | /** | ||
+ | * getTransport | ||
+ | * | ||
+ | * @param | ||
+ | * @return void | ||
+ | | ||
+ | * Đã chuyển logic thành các class thực thi, tuy nhiên khó mở rộng được do function getTransport ngày càng phình to | ||
+ | * Mong muốn khi thêm một loại mới mà không cần cập nhật lại function getTransport -> sử dụng Method Factory Pattern | ||
+ | */ | ||
+ | public static function getTransport($cargoVolume) | ||
+ | { | ||
+ | switch ($cargoVolume) { | ||
+ | case 10: | ||
+ | return new ServiceLogistics(); | ||
+ | case 20: | ||
+ | return new ServiceLogistics(' | ||
+ | default: | ||
+ | return []; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | var_dump(ServiceLogistics:: | ||
+ | |||
+ | </ | ||
+ | |||
+ | **Ví dụ khác:** | ||
+ | |||
+ | <file php> | ||
+ | class XMLParser { | ||
+ | function __construct($filePath) { | ||
+ | file_get_content($filePath); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class JSONParser { | ||
+ | function __construct($filePath) { | ||
+ | file_get_content($filePath); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | abstract class ParserFactory { | ||
+ | public static function __construct($param) { | ||
+ | if ($param[' | ||
+ | return new XMLParser($param[" | ||
+ | } | ||
+ | if ($param[' | ||
+ | return new JSONParser($param[" | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | Ở trên chúng ta có hai class là XMLParser và JSONParser dùng để parse nội dung của tập tin tuỳ thuộc vào tập tin được lưu dưới định dạng là XML hay JSON. Tuy nhiên thay vì tạo parser object trực tiếp từ hai class này mà thông qua một Factory class ParserFactory. | ||
+ | |||
+ | Như ví dụ trên nếu chúng ta thay đổi tên của class XMLParser thì chúng ta chỉ cần thay đổi một dòng code trong method construct của ParserFactory. Nếu như chúng ta không sử dụng Factory thì sẽ phải thay đổi ở tất cả các object được tạo từ class XMLParser. | ||
===== Factory Method Pattern ===== | ===== Factory Method Pattern ===== | ||
Line 15: | Line 128: | ||
{{ : | {{ : | ||
+ | |||
+ | **Tóm lại:** Method Factory dùng khi có nhiều cách thức khác nhau để đạt được 1 mục tiêu, và để khi thêm một cách thức mới thì chúng ta chỉ cần thêm một Class mới tương ứng không phải sửa quá nhiều code trong function xử lý. | ||
+ | |||
+ | **Ví dụ 1:** | ||
+ | |||
+ | {{ : | ||
<file php> | <file php> | ||
Line 132: | Line 251: | ||
</ | </ | ||
- | Trong số những kiểu mẫu thiết kế hay design pattern trong PHP thì Factory là một trong những pattern được sử dụng phổ biến nhất. | + | **Ví dụ 2:** |
+ | |||
+ | {{ : | ||
<file php> | <file php> | ||
- | class XMLParser | + | <?php |
- | function | + | |
- | | + | namespace RefactoringGuru\FactoryMethod\RealWorld; |
+ | |||
+ | /** | ||
+ | * The Creator declares a factory method that can be used as a substitution for | ||
+ | * the direct constructor calls of products, for instance: | ||
+ | * | ||
+ | * - Before: $p = new FacebookConnector(); | ||
+ | * - After: $p = $this-> | ||
+ | * | ||
+ | * This allows changing the type of the product being created by | ||
+ | * SocialNetworkPoster' | ||
+ | */ | ||
+ | abstract | ||
+ | { | ||
+ | | ||
+ | * The actual factory method. Note that it returns the abstract connector. | ||
+ | * This lets subclasses return any concrete connectors without breaking the | ||
+ | * superclass' | ||
+ | */ | ||
+ | abstract public | ||
+ | |||
+ | /** | ||
+ | * When the factory method is used inside the Creator' | ||
+ | * subclasses may alter the logic indirectly by returning different types of | ||
+ | * the connector from the factory method. | ||
+ | */ | ||
+ | public function post($content): void | ||
+ | | ||
+ | | ||
+ | $network = $this-> | ||
+ | // ...then use it as you will. | ||
+ | | ||
+ | $network-> | ||
+ | $network-> | ||
} | } | ||
} | } | ||
- | class JSONParser | + | /** |
- | function __construct($filePath) { | + | * This Concrete Creator supports Facebook. Remember that this class also |
- | | + | * inherits the ' |
+ | * classes that the Client actually uses. | ||
+ | */ | ||
+ | class FacebookPoster extends SocialNetworkPoster | ||
+ | { | ||
+ | | ||
+ | |||
+ | public | ||
+ | | ||
+ | | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | public function getSocialNetwork(): SocialNetworkConnector | ||
+ | { | ||
+ | return new FacebookConnector($this-> | ||
} | } | ||
} | } | ||
- | abstract | + | /** |
- | public | + | * This Concrete Creator supports LinkedIn. |
- | if ($param[' | + | */ |
- | return new XMLParser($param[" | + | class LinkedInPoster extends SocialNetworkPoster |
- | } | + | { |
- | | + | private $email, $password; |
- | return new JSONParser($param[" | + | |
- | } | + | public function __construct(string |
+ | | ||
+ | $this-> | ||
+ | | ||
+ | | ||
+ | |||
+ | public function getSocialNetwork(): SocialNetworkConnector | ||
+ | | ||
+ | return new LinkedInConnector($this-> | ||
} | } | ||
} | } | ||
- | </ | ||
+ | /** | ||
+ | * The Product interface declares behaviors of various types of products. | ||
+ | */ | ||
+ | interface SocialNetworkConnector | ||
+ | { | ||
+ | public function logIn(): void; | ||
- | Ở trên chúng ta có hai class là XMLParser và JSONParser dùng để parse nội dung của tập tin tuỳ thuộc vào tập tin được lưu dưới định dạng là XML hay JSON. Tuy nhiên thay vì tạo parser object trực tiếp từ hai class này mà thông qua một Factory class ParserFactory. | + | public function logOut(): void; |
- | Như ví dụ trên nếu chúng ta thay đổi tên của class XMLParser thì chúng ta chỉ cần thay đổi một dòng code trong method construct của ParserFactory. Nếu như chúng ta không sử dụng Factory thì sẽ phải thay đổi ở tất cả các object | + | public function createPost($content): |
+ | } | ||
+ | |||
+ | /** | ||
+ | * This Concrete Product implements the Facebook API. | ||
+ | */ | ||
+ | class FacebookConnector implements SocialNetworkConnector | ||
+ | { | ||
+ | private $login, $password; | ||
+ | |||
+ | public function __construct(string $login, string $password) | ||
+ | { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | public function logIn(): void | ||
+ | { | ||
+ | echo "Send HTTP API request to log in user $this-> | ||
+ | " | ||
+ | } | ||
+ | |||
+ | public function logOut(): void | ||
+ | { | ||
+ | echo "Send HTTP API request to log out user $this-> | ||
+ | } | ||
+ | |||
+ | public function createPost($content): | ||
+ | { | ||
+ | echo "Send HTTP API requests to create | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * This Concrete Product implements the LinkedIn API. | ||
+ | */ | ||
+ | class LinkedInConnector implements SocialNetworkConnector | ||
+ | { | ||
+ | private $email, $password; | ||
+ | |||
+ | public function __construct(string $email, string $password) | ||
+ | { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | public function logIn(): void | ||
+ | { | ||
+ | echo "Send HTTP API request to log in user $this-> | ||
+ | " | ||
+ | } | ||
+ | |||
+ | public function logOut(): void | ||
+ | { | ||
+ | echo "Send HTTP API request to log out user $this-> | ||
+ | } | ||
+ | |||
+ | public function createPost($content): | ||
+ | { | ||
+ | echo "Send HTTP API requests to create | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * The client code can work with any subclass of SocialNetworkPoster since it | ||
+ | * doesn't depend on concrete classes. | ||
+ | */ | ||
+ | function clientCode(SocialNetworkPoster $creator) | ||
+ | { | ||
+ | // ... | ||
+ | $creator-> | ||
+ | $creator-> | ||
+ | // ... | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * During the initialization phase, the app can decide which social network it | ||
+ | * wants to work with, create an object | ||
+ | * the client code. | ||
+ | */ | ||
+ | echo " | ||
+ | clientCode(new FacebookPoster(" | ||
+ | echo " | ||
+ | |||
+ | echo " | ||
+ | clientCode(new LinkedInPoster(" | ||
+ | </ | ||
===== Abstract Factory Pattern ===== | ===== Abstract Factory Pattern ===== | ||
[[development: | [[development: | ||
+ | |||
+ | ====== Tham khảo ====== | ||
+ | |||
+ | * https:// | ||
+ | * https:// | ||
+ | * https:// |
development/software-architecture/design-patterns/factory.1723775936.txt.gz · Last modified: 2024/08/16 02:38 by tungnt