development:software-architecture:design-patterns:strategy
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:strategy [2024/08/12 16:06] – [Tham khảo] tungnt | development:software-architecture:design-patterns:strategy [2024/08/19 09:41] (current) – tungnt | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Strategy ====== | ====== Strategy ====== | ||
+ | Strategy là một mẫu thiết kế hành vi cho phép xác định một họ thuật toán, đưa từng thuật toán vào một lớp riêng biệt thay vì phải dùng nhiều điều kiện if trong một function - khó tiếp cận và bảo trì. | ||
- | ====== Tham khảo | + | **Ví dụ khi chưa dùng Strategy, đoạn code quá nhiều if dẫn đến khó kiểm soát:** |
+ | |||
+ | <file php> | ||
+ | function getProviderTransfer($userInfo, | ||
+ | { | ||
+ | if(!empty($accountNo) && preg_match('/ | ||
+ | return UserTransaction:: | ||
+ | } | ||
+ | if (!empty($accountNo) && preg_match('/ | ||
+ | return UserTransaction:: | ||
+ | } | ||
+ | if (!empty($options[' | ||
+ | if ($bankInfo-> | ||
+ | return UserTransaction:: | ||
+ | } | ||
+ | |||
+ | if (in_array($bankInfo-> | ||
+ | UserTransaction:: | ||
+ | UserTransaction:: | ||
+ | UserTransaction:: | ||
+ | return $bankInfo-> | ||
+ | } | ||
+ | return UserTransaction:: | ||
+ | } | ||
+ | |||
+ | $appSetting = AppSetting:: | ||
+ | $providerDefault = data_get($appSetting, | ||
+ | |||
+ | if (!empty($userInfo-> | ||
+ | $accountName = !empty($options[' | ||
+ | |||
+ | if ($userInfo-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | if ($userInfo-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | if ($userInfo-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | if ($userInfo-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | $payoutProviderSetting = !empty($userInfo-> | ||
+ | if ($payoutProviderSetting && is_array($payoutProviderSetting) && in_array($bankInfo-> | ||
+ | return $bankInfo-> | ||
+ | } | ||
+ | |||
+ | return strtoupper($userInfo-> | ||
+ | } | ||
+ | |||
+ | if (!empty($options[' | ||
+ | return UserTransaction:: | ||
+ | } | ||
+ | |||
+ | if(!is_numeric($accountNo) && !in_array($bankInfo-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | if (!empty($accountNo) && Bank:: | ||
+ | $bankTransferAtm=data_get($appSetting, | ||
+ | if($bankTransferAtm==UserTransaction:: | ||
+ | { | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | return $bankTransferAtm; | ||
+ | } | ||
+ | if (!empty($accountNo) && Phone:: | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | if (!empty($accountNo) && Bank:: | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | $transferBankSetting = TransferBankPartner:: | ||
+ | -> | ||
+ | -> | ||
+ | if (!$transferBankSetting instanceof TransferBankPartner) { | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | if(in_array($transferBankSetting-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | if ($transferBankSetting-> | ||
+ | && $bankInfo-> | ||
+ | && !Bank:: | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | if ($transferBankSetting-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | if ($transferBankSetting-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | if ($transferBankSetting-> | ||
+ | return $providerDefault; | ||
+ | } | ||
+ | |||
+ | return $transferBankSetting-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | **Ví dụ 1:** | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | <file php> | ||
+ | <?php | ||
+ | |||
+ | namespace RefactoringGuru\Strategy\Conceptual; | ||
+ | |||
+ | /** | ||
+ | * The Context defines the interface of interest to clients. | ||
+ | */ | ||
+ | class Context | ||
+ | { | ||
+ | /** | ||
+ | * @var Strategy The Context maintains a reference to one of the Strategy | ||
+ | * objects. The Context does not know the concrete class of a strategy. It | ||
+ | * should work with all strategies via the Strategy interface. | ||
+ | */ | ||
+ | private $strategy; | ||
+ | |||
+ | /** | ||
+ | * Usually, the Context accepts a strategy through the constructor, | ||
+ | * provides a setter to change it at runtime. | ||
+ | */ | ||
+ | public function __construct(Strategy $strategy) | ||
+ | { | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Usually, the Context allows replacing a Strategy object at runtime. | ||
+ | */ | ||
+ | public function setStrategy(Strategy $strategy) | ||
+ | { | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * The Context delegates some work to the Strategy object instead of | ||
+ | * implementing multiple versions of the algorithm on its own. | ||
+ | */ | ||
+ | public function doSomeBusinessLogic(): | ||
+ | { | ||
+ | // ... | ||
+ | |||
+ | echo " | ||
+ | $result = $this-> | ||
+ | echo implode(",", | ||
+ | |||
+ | // ... | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * The Strategy interface declares operations common to all supported versions | ||
+ | * of some algorithm. | ||
+ | * | ||
+ | * The Context uses this interface to call the algorithm defined by Concrete | ||
+ | * Strategies. | ||
+ | */ | ||
+ | interface Strategy | ||
+ | { | ||
+ | public function doAlgorithm(array $data): array; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Concrete Strategies implement the algorithm while following the base Strategy | ||
+ | * interface. The interface makes them interchangeable in the Context. | ||
+ | */ | ||
+ | class ConcreteStrategyA implements Strategy | ||
+ | { | ||
+ | public function doAlgorithm(array $data): array | ||
+ | { | ||
+ | sort($data); | ||
+ | |||
+ | return $data; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | class ConcreteStrategyB implements Strategy | ||
+ | { | ||
+ | public function doAlgorithm(array $data): array | ||
+ | { | ||
+ | rsort($data); | ||
+ | |||
+ | return $data; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * The client code picks a concrete strategy and passes it to the context. The | ||
+ | * client should be aware of the differences between strategies in order to make | ||
+ | * the right choice. | ||
+ | */ | ||
+ | $context = new Context(new ConcreteStrategyA()); | ||
+ | echo " | ||
+ | $context-> | ||
+ | |||
+ | echo " | ||
+ | |||
+ | echo " | ||
+ | $context-> | ||
+ | $context-> | ||
+ | </ | ||
+ | |||
+ | **Ví dụ 2:** | ||
+ | |||
+ | <file php PaymentMethodInterface.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Services\Payment; | ||
+ | |||
+ | interface PaymentMethodInterface | ||
+ | { | ||
+ | /** | ||
+ | * pay | ||
+ | * | ||
+ | * @return string | ||
+ | */ | ||
+ | public function pay(): string; | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <file php CreditCardService.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Services\Payment; | ||
+ | |||
+ | /** | ||
+ | * CreditCardService | ||
+ | */ | ||
+ | class CreditCardService implements PaymentMethodInterface | ||
+ | { | ||
+ | |||
+ | /** | ||
+ | * pay | ||
+ | * | ||
+ | * @return string | ||
+ | */ | ||
+ | public function pay(): string{ | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <file php ApplePayService.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Services\Payment; | ||
+ | |||
+ | /** | ||
+ | * ApplePayService | ||
+ | */ | ||
+ | class ApplePayService implements PaymentMethodInterface | ||
+ | { | ||
+ | |||
+ | /** | ||
+ | * pay | ||
+ | * | ||
+ | * @return string | ||
+ | */ | ||
+ | public function pay(): string{ | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <file php GooglePayService.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Services\Payment; | ||
+ | |||
+ | /** | ||
+ | * GooglePayService | ||
+ | */ | ||
+ | class GooglePayService implements PaymentMethodInterface | ||
+ | { | ||
+ | |||
+ | /** | ||
+ | * pay | ||
+ | * | ||
+ | * @return string | ||
+ | */ | ||
+ | public function pay(): string{ | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <file php PaymentContextService.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Services\Payment; | ||
+ | |||
+ | /** | ||
+ | * PaymentContextService | ||
+ | */ | ||
+ | class PaymentContextService | ||
+ | { | ||
+ | |||
+ | /** | ||
+ | * @var PaymentMethodInterface | ||
+ | */ | ||
+ | private $paymentMethod; | ||
+ | |||
+ | /** | ||
+ | * __construct | ||
+ | * | ||
+ | * @param | ||
+ | * @return void | ||
+ | */ | ||
+ | public function __construct(string $paymentMethod) | ||
+ | { | ||
+ | $this-> | ||
+ | ' | ||
+ | ' | ||
+ | ' | ||
+ | default => throw new \InvalidArgumentException(" | ||
+ | }; | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * pay | ||
+ | * | ||
+ | * @return string | ||
+ | */ | ||
+ | public function pay(){ | ||
+ | return $this-> | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </ | ||
+ | |||
+ | <file php StrategyCommand.php> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Console\Commands\Test; | ||
+ | |||
+ | use App\Services\Payment\PaymentContextService; | ||
+ | use Illuminate\Console\Command; | ||
+ | |||
+ | /** | ||
+ | * Class StrategyCommand | ||
+ | * @package Modules\Web\Console\Commands | ||
+ | */ | ||
+ | class StrategyCommand extends Command | ||
+ | { | ||
+ | /** | ||
+ | * The console command name. | ||
+ | * | ||
+ | * @var string | ||
+ | */ | ||
+ | protected $signature = ' | ||
+ | |||
+ | /** | ||
+ | * The console command description. | ||
+ | * | ||
+ | * @var string | ||
+ | */ | ||
+ | protected $description = "Test Cms module command"; | ||
+ | |||
+ | public function handle(){ | ||
+ | //$result = $this-> | ||
+ | $result = $this-> | ||
+ | |||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | private function strategy($paymentMethod){ | ||
+ | $payment = new PaymentContextService($paymentMethod); | ||
+ | |||
+ | return $payment-> | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * normal | ||
+ | * | ||
+ | * @param | ||
+ | * @return string | ||
+ | */ | ||
+ | private function normal($paymentMethod){ | ||
+ | if(' | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | if(' | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | if(' | ||
+ | return ' | ||
+ | } | ||
+ | |||
+ | throw new \InvalidArgumentException(" | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Tham khảo ===== | ||
* https:// | * https:// | ||
+ | * https:// | ||
* https:// | * https:// | ||
* https:// | * https:// | ||
development/software-architecture/design-patterns/strategy.1723478792.txt.gz · Last modified: 2024/08/12 16:06 by tungnt