분류 php

PHP 애플리케이션에서 사용되는 상위 5 가지 디자인 패턴

컨텐츠 정보

  • 조회 28 (작성일 )

본문

아시나요? PHP는 서버 측 언어를 사용하는 웹 사이트의 78.9 %에서 사용됩니다!


많은 조직이 훌륭한 애플리케이션을 구축하는 데 도움을 줄 수 있는 PHP 개발자를 고용하고 있습니다. 방문하는 거의 8/10 웹 사이트에서 어떤식으로든 PHP를 사용하는 경우 PHP 애플리케이션을 만드는 데 사용되는 디자인 패턴에 대해 아는 것이 좋습니다.


다음은 PHP 애플리케이션을 만드는 데 사용되는 5 가지 디자인 패턴입니다.


https://www.discussdesk.com/top-5-design-patterns-used-in-php-applications.htm


Factory 


팩토리 패턴은 개체를 만들 때 이상적입니다. 새 개체를 만들 때는 개체를 만든 다음 초기화해야 합니다. 일반적으로 특정 논리를 적용하려면 여러 단계를 수행해야 합니다. 모든 단계가 포함되어 있으므로 모든 단계를 한곳에 두고 같은 방식으로 새 개체를 만들어야 할 때마다 다시 사용하는 것이 좋습니다. 이것이 공장 패턴이 작동하는 방식입니다.


코드 예제로 이해합시다.


interface FriendFactoryInterface { public function create() : Friend } 


그런 다음 다음 클래스를 사용하여 팩토리 인터페이스를 구현합니다.


class FriendFactory implements FriendFactoryInterface { public function create() : Friend { $friend = new Friend(); // initialize your friend return $friend; } } 


Pros 

  • 응용 프로그램의 이음새를 쉽게 테스트
  • 응용 프로그램의 디자인을 쉽게 변경

Cons 

  • 코드를 읽기 어렵게 만듭니다.
  • 잘못 사용하면 안티 패턴으로 분류 될 수 있습니다.

또한 읽을 수 있습니다 : PHP 및 Mysql로 ​​간단한 쇼핑 카트 만들기


Strategy 


전략 디자인 패턴을 사용하면 작업을 수행하는 데 필요한 알고리즘의 구현 세부 정보를 숨길 수 있습니다. 또한 클라이언트는 실제 구현을 모르고 작업을 수행하기 위해 적용하지 않고도 필요한 알고리즘을 갖도록 선택할 수 있습니다.


예를 들어 스프레드 시트의 데이터를 문서 파일로 전송해야 하는 경우입니다.


먼저 스프레드 시트와 데이터베이스의 저장소에서 데이터를 읽는 전략을 만들어야 합니다. 전략의 이름을 "독자"로 지정할 수 있습니다. 다음으로 스토리지에 데이터를 쓰는 전략을 만들어야 합니다. 우리는 그들을“작가”라고 부르도록 선택할 수 있습니다.


따라서 이제 스프레드 시트 또는 데이터베이스에서 데이터를 읽을 두 명의 독자가 있습니다. 마찬가지로 스프레드 시트 나 doc 파일에 데이터를 쓰는 두 명의 작성자가 있습니다.


또한 함께 작업 할 클라이언트는 구현에 대해 전혀 알지 못합니다. 따라서 전략에 대한 인터페이스를 정의해야 합니다.


마지막으로 전략을 선택한 다음 데이터를 전송할 클라이언트를 만들어야 합니다.


실행 방법은 다음과 같습니다.


interface ReaderInterface { public function start() : void; public function read() : array; public function stop() : void; } interface WriterInterface { public function start() : void; public function write(array $data) : void; public function stop() : void; } class DatabaseReader implements ReaderInterface { ... } class SpreadsheetReader implements ReaderInterface { ... } class CsvWriter implements WriterInterface { ... } class JsonWriter implements WriterInterface { ... } class Transformer { ... public function transform(string $from, string $to) : void { $reader = $this->findReader($from); $writer = $this->findWriter($to); $reader->start(); $writer->start(); try { foreach ($reader->read() as $row) { $writer->write($row); } } finally { $writer->stop(); $reader->stop(); } } ... } 


이 코드에서 변환기 (클라이언트)는 작동하는 구현에 대해 걱정하지 않습니다. 우리의 전략 인터페이스에서 거부 한 메서드에만 관심이 있습니다.


Pros: 

  • 조건문 사용 방지 (switch, if, else)
  • 컨텍스트 엔티티를 변경하지 않고 알고리즘을 변경 / 대체 할 수 있습니다.
  • 쉽게 확장 가능

Cons: 

  • 클라이언트는 다른 전략의 존재를 인식해야 합니다.
  • 응용 프로그램의 개체 수를 늘립니다.

Adapter 


어댑터 디자인 패턴을 사용하면 외부 인터페이스를 공통 인터페이스로 전환 할 수 있습니다. 다음 클래스를 사용하여 일부 저장소에서 데이터를 가져 온다고 가정 해 보겠습니다.


class Storage { private $source; public function __constructor(AdapterInterface $source) { $this->source = $source; } public function getOne(int $id) : ?object { return $this->source->find($id); } public function getAll(array $criteria = []) : Collection { return $this->source->findAll($criteria); } } 


저장소는 소스에서 직접 작동하지 않지만 소스의 어댑터에서 작동합니다. 또한 저장소는 구체적인 어댑터에 대해 아무것도 모르고 어댑터 인터페이스 만 알고 있습니다. 따라서 어댑터의 구현은 스토리지에 대한 알 수 없는 영역입니다.


다음은 어댑터 인터페이스의 예입니다.


interface AdapterInterface { public function find(int $id) : ?object; public function findAll(array $criteria = []) : Collection; } 


이제 MySQL 데이터베이스에 액세스하기 위해 라이브러리를 사용한다고 가정 해 보겠습니다. 라이브러리는 자체 인터페이스를 지정하며 다음과 같습니다.


$row = $mysql->fetchRow(...); $data = $mysql->fetchAll(...); class MySqlAdapter implements AdapterInterface { ... public function find(int $id) : ?object { $data = $this->mysql->fetchRow(['id' => $id]); // some data transformation } public function findAll(array $criteria = []) : Collection { $data = $this->mysql->fetchAll($criteria); // some data transformation } ... } 


그 후 다음과 같이 스토리지에 주입 할 수 있습니다.


$storage = new Storage(new MySqlAdapter($mysql)); 


나중에 다른 라이브러리를 사용하기로 결정한 경우 해당 라이브러리에 대해 다른 어댑터를 만든 다음 새 어댑터를 스토리지에 삽입하기 만하면 됩니다. 흥미롭게도 스토리지 클래스에 있는 항목을 건드릴 필요가 없습니다. 이것이 바로 어댑터 디자인 패턴의 장점입니다.


Pros: 

  • 재사용 성 및 유연성 향상
  • 클라이언트가 단순화 됨
  • 최소화 된 결합


Cons: 


  • 과도한 엔지니어링에 취약
  • 토끼 흔적 효과에 민감합니다. 중첩 된 개체가 있는 경우 어댑터는 프로세스를 연장 할 수 있습니다. Person을 로드하기 위해 AdapterC를 호출하는 AdapterB를 호출하는 AdapterA로 끝날 수 있습니다.

이 단계에서 읽을 수 있습니다 .php를 사용하여 QR 코드를 생성하는 방법


Observer 


관찰자 디자인 패턴은 특정 이벤트에 대해 시스템에 알려야 할 때 유용합니다. 예를 들어 비평가에게 영화를 상영하기 위해 "극장"이라는 이벤트를 만들어야 합니다. 그러나 휴대 전화로 메시지를 보내야 합니다. 그런 다음 영화 중간에 5 분 동안 영화를 중지하여 평론가가 휴식을 취할 수 있도록 합니다. 마지막으로 영화가 끝난 후에는 평론가의 피드백을 수집해야 합니다.


이것이 코드에서 어떻게 보이는지 보겠습니다.


class Theater { public function present(Movie $movie) : void { $critics = $movie->getCritics(); $this->messenger->send($critics, '...'); $movie->play(); $movie->pause(5); $this->progress->break($critics) $movie->finish(); $this->feedback->request($critics); } } 



이제 잠시 후 영화를 시작하기 전에 그런 느낌이 들면 조명도 꺼야 합니다. 또한 간격에 광고를 표시 할 수도 있습니다. 또한 영화가 끝나면 방의 자동 청소를 시작하고 싶을 것입니다.


Observer 패턴은 극장 클래스에 더 많은 복잡성을 추가하는 대신 시스템 전체에 복잡성을 분산하는 데 도움이 됩니다.


작동 방식은 다음과 같습니다.


class Theater { public function present(Movie $movie) : void { $this->getEventManager() ->notify(new Event(Event::START, $movie)); $movie->play(); $movie->pause(5); $this->getEventManager() ->notify(new Event(Event::PAUSE, $movie)); $movie->finish(); $this->getEventManager() ->notify(new Event(Event::END, $movie)); } } $theater = new Theater(); $theater ->getEventManager() ->listen(Event::START, new MessagesListener()) ->listen(Event::START, new LightsListener()) ->listen(Event::PAUSE, new BreakListener()) ->listen(Event::PAUSE, new AdvertisementListener()) ->listen(Event::END, new FeedbackListener()) ->listen(Event::END, new CleaningListener()); $theater->present($movie); 


따라서 Observer 디자인 패턴은 단순히 사실에 대해 나머지 시스템에 알립니다. 또한 복잡성을 추가하는 것도 쉬워집니다. 새 리스너를 만들고 여기에 필요한 로직을 입력하기 만하면 됩니다.


Pros: 

  • 효율적인 방식으로 객체에 데이터를 보낼 수 있습니다.
  • 새로운 관찰자를 추가하기 위해 주제를 수정하지 않습니다.
  • 언제든지 관찰자를 추가 및 제거 할 수 있습니다.

Cons 

  • 인터페이스에 대한 프로그래밍과 상속의 강제 사용
  • 관찰자 패턴은 불필요한 복잡성을 추가 할 수 있습니다.
  • 관찰자 알림의 순서는 필수입니다.

이 단계에서 다음을 읽을 수도 있습니다. 다음 웹 디자인 프로젝트에 시도 할 5 가지 웹 디자인 트렌드 


Decorator 


데코레이터 디자인 패턴은 런타임에 개체의 동작을 조정하려는 경우에 사용됩니다. 또한 클래스 수를 줄이고 중복 상속을 줄이는 데 도움이 됩니다.


코드 예제로 이것을 이해합시다.


interface OpenerInterface { public function open() : void; } class Door implements OpenerInterface { public function open() : void { // opens the door } } class Window implements OpenerInterface { public function open() : void { // opens the window } } class SmartDoor extends Door { public function open() : void { parent::open(); $this->temperature(); } } class SmartWindow extends Window { public function open() : void { parent::open(); $this->temperature(); } } 


총 4 개의 class이 있습니다. 그러나 데코레이터 패턴을 사용하면 3 개의 클래스로만 이 문제를 해결할 수 있습니다.


class SmartOpener implements OpenerInterface { private $opener; public function __construct(OpenerInterface $opener) { $this->opener = $opener; } public function open() : void { $this->opener->open(); $this->temperature(); } } $door = new Door(); $window = new Window(); $smartDoor = new SmartOpener($door); $smartWindow = new SmartOpener($window); 


Pros: 


  • 기능 확장을 위한 서브 클래 싱에 대한 유연한 대안
  • 런타임시 동작 수정 허용
  • 순열 문제에 대한 이상적인 솔루션
  • 클래스는 확장을 위해 열리고 수정을 위해 닫히는 원칙을 지원합니다.

Cons: 

  • 복잡성을 유발할 수 있는 작은 물체가 많을 수 있습니다.
  • 데코레이터는 복잡 할 수 있습니다.

이것은 PHP 애플리케이션에서 일반적으로 사용되는 디자인 패턴입니다. 웹 개발자와 디자이너가 효율성을 높이고 생산성을 높이는 데 도움이 됩니다.