구조패턴 - 어댑터 패턴 (쉽게 배워 바로 써먹는 디자인 패턴)

모험가·2022년 11월 18일
0
post-thumbnail

⚙️ 어댑터 패턴

어댑터 패턴은 코드를 재사용하기위해 구조를 변경하는 패턴입니다.
(구조 패턴중 가장 간단합니다 ^__^)


어댑터

어댑터 패턴은 다른 말로 래퍼 패턴(wrapper pattern)이라고 합니다. 래퍼는 감싸다는 의미로, 기존의 클래스를 새로운 클래스로 감싸는 기법 입니다. 래퍼 처리로 기존의 기능은 유지하면서 변경된 추가 코드를 삽입합니다.

래퍼 처리된 객체를 어댑터라고 합니다.

직접 사진찍은건데 좀 짜그라졌네요.

  • 어댑터 : 변환을 처리하는 객체
  • 어댑티 : 변환을 받아 사용하는 객체

어댑터 종류

어댑터는 다른 객체의 구조를 내가 원하는 인터페이스 방식으로 개선합니다. 구조를 개선하는 방법은 클래스의 상속을 이용하는 방법과 구성을 이용하는 방법 2가지 입니다.

  • 클래스 어댑터 : 상속
  • 객체 어댑터 : 구성

클래스 어댑터

클래스 어댑터는 클래스의 상속 특성을 이용하며, 클래스 어댑터를 사용하기 위해서는 다중 상속이 필요합니다.

다중 상속이란 하나의 클래스가 2개 이상의 클래스에서 상속되는것을 말 합니다. 클래스 어댑터는 2개의 클래스를 받아 기존 클래스의 메서드를 다른 메서드로 대체하는 방법입니다.

근데.. 그거 아십니까 최신 프로그래밍 언어는 다중 상속을 지원하지 않습니다. php와 java또한 단일상속만 지원합니다. 다중 상속에서는 클래스 메서드의 충돌이 발생합니다.

아무래도 최신 언어로 다중상속을 이용하여 클래스 어댑터를 표현하기는 어렵겠습니다.

그러나 클래스 어댑터는 별도의 어댑티를 만들지 않으며, 하나의 클래스로 어댑티 객체를 처리할 수 있다는 장접이 있습니다.

객체 어댑터

객체 어댑터는 객체의 의존성을 이용해 문제를 해결합니다. 객체 어댑터는 기존 타깃인 객체의 인터페이스에 영향을 받으며, 타깃의 인터페이스가 복잡할수록 많은 작업이 필요합니다.

객체 어댑터는 내부적으로 객체를 재구성합니다. 구성을 위해 기존 객체는 복합 객체로 변환됩니다.

어댑터는 인터페이스를 변경합니다. 하지만 어댑터는 인터페이스로 캡술화 됐기 때문에 클라이언트에서 변화를 눈치채지 못한채 그대로 사용할 수 있습니다. 어댑터 패턴은 객체의 호환성을 개선하기 위한 기능들로 새롭게 합성합니다.

객체를 구성으로 결합하면 느슨한 연결 방식으로, 보다 많은 유연성을 확보할 수 있다는 장점이 있습니다. 그리고 구성은 프로그램 실행 도중에도 객체를 변경할 수 있습니다.


예제

⛏️ 기존 코드

<php 
//원본소스 
class Math
{
	//입력한 값이 2배 증가합니다.
	// 입력값과 반환값은 float형입니다.
	public function twoTime (float $num): float
	{
		echo "실수 2배 적용합니다. In"
		return $num*2;
	}
	//입력한 값이 절반으로 감소합니다.
	// 입력값과 반환값은 float형입니다.
	public function halfTime(float $num): float
	{
	echo "실수 1/2배 적용합니다. In";
	return $num/2;
    }
}

곱셈을 계산하는 메서드 입니다. 매개변수 인자로 실수값을 받습니다.

만약 인자값이 정수로 변경된다고 가정하면, 더이상 이 Math 클래스를 사용할 수 없습니다. 우리는 어댑터 패턴으로 이 문제를 해결할거에요.

⛏️ 어댑터 제작

<?php
// 어댑터 인터페이스
interface Adapter
{
	public function twice0f(int $num):int; 
    public function half0f(int $num):int;
}

인터페이스에서 입력한 값을 보정합니다. 정수 타입으로 지정한 후, 알맞는 구체 클래스를 만듭니다.
+) 인터페이스 변경을 담당하는 클래스를 플러그블 어댑터라고 합니다.

⛏️ 구현 코드

<?php
//새롭게 구현된 코드
class Objects implements Adapter
{
	private $_adapter;
	
    function _construct()
	{
	//기존 클래스의 객체를 생성합니다.
	$this->_adapter = new math;
	}

	public function twice0f (int $num):int
	{
		echo "정수 2배 적용합니다. n";
		//캐스팅을 통해 실수로 변환하여 전달합니다.
		$_num = $this->_adapter->twoTime( (float)$num );
		//캐스팅을 통해 정수로 변환하여 반환합니다.
		return (int)$_num;
	}

	public function half0f(int $num): int
	{
		echo "정수 1/2배 적용합니다. \n";
		
        //캐스팅을 통해 실수로 변환하여 전달합니다.
		$num = $this->_adapter->halfTime( (float)$num );
		//캐스팅을 통해 정수로 변환하여 반환합니다.
		return (int)$_num;
	}
}

작성한 어댑터는 기존의 Math 클래스를 상속받지 않습니다. 그 대신 객체의 생성자에서 기존 Math 클래스의 객체를 생성합니다. 어댑터는 생성자에서 새로운 객체를 생성, 포함함으로 복합객체 입니다.

입력된 정숫값을 실숫값으로 캐스팅하고, 기존 Math클래스의 메서드를 호출합니다. 결과값도 캐스팅해서 정수값으로 변경한 후 반환됩니다.

⛏️ 클라이언트 코드

?php 
include "Math.php";
include "Adapter.php";
include "Object.php";

sobi = new Objects;

//어댑터를 이용하여 두 배 계산합니다.
echo $obj->twice0f(5);
echo "\n";

//어댑터를 이용하여 절반을 계산합니다.
echo $obj-half0f(4);

이제 실행해볼까요.

일단 지금은 책에 있는 예제인데 자고 일어나서 테스트해보고 제가 한 예제로 바꿀게요 ><

이처럼 어댑터 패턴을 이용하면 클래스와 메서드를 수정하지 않고, 원하는 형태로 변경 할 수 있습니다.

어댑터 패턴은 한국에서 사용되는 220V 가전제품을 
일본에서 110V에 연결하기 위해 
변환 어댑터와 같은 컨버터를 사용하는 것으로 비유할 수 있습니다.

실습하실 분들을 위해,, 예제 코드를 올려드립니다. 제가 다 쳤습니다.
사실 아니고 아이폰 짱짱맨이 텍스트 읽어줘서 수정 조금만 했습니다.
증말 최고.

profile
부산 싸나이의 모험기

0개의 댓글