어댑터 패턴
Coddy PHP 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 91개 중 76번째.
어댑터 패턴은 호환되지 않는 인터페이스를 가진 객체들이 함께 작동할 수 있도록 하는 구조적 디자인 패턴입니다. 두 인터페이스 사이의 다리 역할을 하며, 한 형식의 호출을 다른 형식으로 변환합니다.
결제를 처리하는 application을 구축하고 있는데 타사 결제 library를 통합해야 한다고 상상해 보세요. library는 완벽하게 작동하지만 해당 interface가 코드에서 expects하는 것과 일치하지 않습니다. 전체 application을 다시 작성하는 대신, 두 가지 사이를 변환하는 adapter를 만듭니다.
<?php
// 애플리케이션이 기대하는 인터페이스
interface PaymentProcessor {
public function pay(float $amount): string;
}
// 다른 인터페이스를 가진 타사 라이브러리
class StripeAPI {
public function createCharge(int $cents, string $currency): string {
return "Charged {$cents} {$currency} via Stripe";
}
}
adapter는 내부적으로 타사 클래스를 사용하면서 예상한 interface를 구현합니다:
<?php
class StripeAdapter implements PaymentProcessor {
public function __construct(private StripeAPI $stripe) {}
public function pay(float $amount): string {
$cents = (int)($amount * 100);
return $this->stripe->createCharge($cents, 'USD');
}
}
$stripe = new StripeAPI();
$processor = new StripeAdapter($stripe);
echo $processor->pay(29.99);
출력:
Charged 2999 USD via Stripeadapter는 달러를 cents로 변환하고 적절한 method를 호출합니다. application 코드는 PaymentProcessor에 대해서만 알고 있으므로 Stripe의 구체적인 요구 사항은 전혀 알지 못합니다. 나중에 different 결제 제공업체로 전환하더라도 기존 코드를 변경하지 않고 새 adapter를 만들기만 하면 됩니다.
챌린지
쉬움Adapter Pattern을 사용하여 온도 변환 시스템을 만들어 보겠습니다. Fahrenheit 단위로 측정값을 출력하는 레거시 온도 센서가 있지만, 최신 날씨 application은 모든 온도를 Celsius로 예상합니다. 어느 시스템도 수정하는 대신, 그 차이를 연결하는 adapter를 Create하겠습니다.
코드를 네 개의 파일로 구성합니다:
TemperatureSensor.php: 날씨 application이 예상하는TemperatureSensorinterface를 Define합니다. Celsius 단위의 온도를 반환하는getTemperature(): floatmethod가 있어야 합니다.LegacySensor.php: 기존 hardware를 시뮬레이션하는LegacySensorclass를 Create합니다. 이 class는 application에 필요한 것과 다른 interface를 have 있습니다:- constructor에서 Fahrenheit 측정값을 받습니다(constructor promotion을 사용하세요).
- 저장된 Fahrenheit 값을 반환하는
readFahrenheit(): floatmethod가 있습니다.
LegacySensorAdapter.php: TemperatureSensor interface와 LegacySensor class를 모두 Include합니다.TemperatureSensor를 implements하고LegacySensor를 감싸는LegacySensorAdapterclass를 Create합니다. adapter는 다음을 수행해야 합니다:- constructor에서
LegacySensor를 Accept합니다. - legacy sensor에서 Fahrenheit 값을 읽고 다음 formula를 사용하여 Celsius로 converts하여
getTemperature()를 Implement합니다:(fahrenheit - 32) * 5 / 9
- constructor에서
main.php: LegacySensorAdapter 파일을 Include합니다. 하나의 input, 즉 Fahrenheit 단위의 온도를 받습니다.input 온도로
LegacySensor를 Create한 다음, 이를LegacySensorAdapter로 감쌉니다. adapter에서getTemperature()를 Call하고 결과를 소수점 둘째 자리까지 반올림하여 출력합니다.Output format은 다음과 같아야 합니다:
Temperature: [celsius]C
이 challenge는 Adapter Pattern을 사용하면 기존 코드를 수정하지 않고도 호환되지 않는 interface를 통합할 수 있음을 보여 줍니다. 날씨 application은 TemperatureSensor interface만을 사용하므로, 실제 측정값이 레거시 Fahrenheit 센서에서 제공된다는 사실을 전혀 알지 못합니다.
직접 해보기
<?php
require_once 'LegacySensorAdapter.php';
// 입력 읽기
$fahrenheit = floatval(trim(fgets(STDIN)));
// TODO: 입력 온도로 LegacySensor 생성
// TODO: LegacySensorAdapter로 감싸기
// TODO: 어댑터에서 getTemperature() 호출
// TODO: 결과를 소수점 두 자리로 반올림하여 출력
// 출력 형식: Temperature: [celsius]C
?>이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 PHP 컴파일러