전략 패턴
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 74번째.
Strategy Pattern은 알고리즘군을 정의하고, 각 알고리즘을 자체 클래스에 캡슐화하며, 런타임에 서로 교체할 수 있도록 하는 행위 디자인 패턴입니다. 전략을 사용하는 객체는 어떤 알고리즘을 실행하는지 알 필요가 없습니다.
서로 다른 할인 전략을 적용할 수 있는 쇼핑 cart를 상상해 보세요. 조건문으로 할인 로직을 하드코딩하는 대신, 각 할인을 별도의 클래스로 define합니다:
<?php
interface DiscountStrategy {
public function calculate(float $total): float;
}
class NoDiscount implements DiscountStrategy {
public function calculate(float $total): float {
return $total;
}
}
class PercentageDiscount implements DiscountStrategy {
public function __construct(private int $percent) {}
public function calculate(float $total): float {
return $total - ($total * $this->percent / 100);
}
}
class FixedDiscount implements DiscountStrategy {
public function __construct(private float $amount) {}
public function calculate(float $total): float {
return max(0, $total - $this->amount);
}
}
context class는 모든 전략을 수용하고 계산을 delegates합니다:
<?php
class ShoppingCart {
public function __construct(private DiscountStrategy $discount) {}
public function setDiscount(DiscountStrategy $discount): void {
$this->discount = $discount;
}
public function checkout(float $total): float {
return $this->discount->calculate($total);
}
}
$cart = new ShoppingCart(new NoDiscount());
echo $cart->checkout(100) . "\n";
$cart->setDiscount(new PercentageDiscount(20));
echo $cart->checkout(100);
출력:
100
80Strategy 패턴은 작업을 수행하는 여러 방법이 있고, 이를 사용하는 class를 수정하지 않고 방법을 전환하고 싶을 때 빛을 발합니다. 새로운 discount 유형을 추가하려면 기존 코드를 수정하는 것이 아니라 새로운 class를 만들면 됩니다.
챌린지
쉬움Strategy Pattern을 사용하여 배송비 계산기를 만들어 봅시다. 배송 방법마다 가격 책정 규칙이 다릅니다. standard 배송은 고정 요금을 부과하고, express 배송은 비율을 추가하며, overnight 배송은 두 가지를 결합합니다. Strategy Pattern을 사용하면 이를 사용하는 코드를 변경하지 않고 이러한 계산을 교체할 수 있습니다.
코드를 네 개의 파일로 구성합니다.
ShippingStrategy.php: 모든 배송 방법에 대한contract을 define하는ShippingStrategyinterface를 Create합니다. 패키지의 무게를 입력으로 받아 배송비를 반환하는calculate(float $weight): floatmethod가 있어야 합니다.ShippingMethods.php: ShippingStrategy 파일을 포함하고 interface를 implements하는 세 개의 class를 Create합니다.StandardShipping: 무게와 관계없이$5.00의 flat rate를 부과합니다.ExpressShipping: kilogram당$2.00를 부과합니다(무게에 2를 곱합니다).OvernightShipping: base fee$10.00에 kilogram당$3.00를 더해 부과합니다.
ShippingCalculator.php: ShippingStrategy 파일을 포함하고 context 역할을 하는ShippingCalculatorclass를 Create합니다. calculator는 다음과 같아야 합니다.- constructor에서
ShippingStrategy를 Accept합니다(constructor promotion 사용). - runtime에 배송 방법을 change하기 위한
setStrategy(ShippingStrategy $strategy): voidmethod를 Have합니다. - current strategy에 delegates하는
calculateCost(float $weight): floatmethod를 Have합니다.
- constructor에서
main.php: ShippingMethods 및 ShippingCalculator 파일을 포함합니다. 두 가지 input을 받습니다. 배송 type("standard","express"또는"overnight")과 패키지 무게입니다.StandardShipping으로 시작하는ShippingCalculator를 Create합니다. 배송 type input을 Based로setStrategy()를 사용하여 appropriate 배송 방법으로 switch합니다. 그런 다음 given 무게에 대한 cost를 Calculate하고, 결과를 소수점 둘째 자리까지 formatted하여 출력합니다.출력은 다음과 같아야 합니다:
Shipping cost: $[cost]
이 challenge는 Strategy Pattern이 배송 시스템을 어떻게 유연하게 만드는지 보여 줍니다. SameDayShipping과 같은 새로운 배송 방법을 추가할 때 calculator나 기존 배송 방법을 수정하지 않고 interface를 implements하는 새 class만 Create하면 됩니다.
직접 해보기
<?php
require_once 'ShippingMethods.php';
require_once 'ShippingCalculator.php';
// 입력 읽기
$shippingType = trim(fgets(STDIN));
$weight = floatval(fgets(STDIN));
// TODO: StandardShipping으로 시작하는 ShippingCalculator 생성
// TODO: 배송 유형 입력("standard", "express", 또는 "overnight")에 따라,
// setStrategy()를 사용하여 적절한 배송 방법으로 전환
// TODO: 주어진 무게에 대한 비용 계산
// TODO: 결과를 소수점 두 자리로 포맷하여 출력
// Output format: Shipping cost: $[cost]
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 PHP 컴파일러