프로그래밍/Php

[디자인패턴] php 로 알아보는 Builder pattern

소행성왕자 2020. 4. 24. 10:17

"빌더 패턴(Builder pattern)이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다." 라고 하는데 무슨말인지 잘 모르겠다.

 

쉽게 설명해볼께요.

php를 이용한 크롤링(파싱) 을 거의 15년 이상 개발하는 동안 코드를 좀 더 편하게 / 좀 더 모듈로 만들면 어떨까 라는 생각이 시작점입니다.

 

예를 들어볼께요

파싱할때에 꼭 필요한 부분이 아래 3개 입니다.

추가적으로 로그인 해야 하는 사이트는 쿠키 / 헤더 가 포함됩니다.

그렇다면 아래와 같은 정보를 생성자에게 넘겨주려고하면 인자가 많아집니다.

 

  - url / agent / referer 

 

보통 아래와 같이 코드를 생성합니다.

<?php
class Parsing
{
private $url;
private $refer;
private $agent;
public function __construct($url, $refer, $agent) {
$this->url = $url;
$this->refer = $refer;
$this->agent = $agent;
}
}

 

만약 여기에 쿠키, 헤더 등등 더 추가해야 된다고 한다면 아래와 같이 인자값이 늘어나겠죠.

 

<?php
class Parsing
{
private $url;
private $refer;
private $agent;
private $cookie;
private $headers;
public function __construct($url, $refer, $agent, $cookie, $headers) {
$this->url = $url;
$this->refer = $refer;
$this->agent = $agent;
$this->cookie = $cookie;
$this->headers = $headers;
}
}

 

 

Builder pattern 을 모를때에는 인자를 배열 또는 객체에 몽땅 때려놓고 인자로 넘겼습니다.

<?php
$par = new Parsing(new Config());
<?php
class Config
{
private $url;
private $refer;
private $agent;
private $cookie;
private $headers;
public function __construct() {
$this->url = "http://~~~";
$this->refer = "http://~~~";
$this->agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36";
$this->cookie = $cookie;
$this->headers = [
'Content-Type' => 'application/x-www-form-urlencoded',
'Upgrade-Insecure-Requests' => '1'
];
}
....
}

 

이렇게 하다보니 뭔가 어색한 설정파일을 하나 더 만들어야 된다는 번거로움이 생기게 되더군요.

더 좋은 코드가 없나 찾아보는 도중 Builder pattern 이란것을 발견했습니다.

Builder pattern 에 대해서는 여기를 참고하시면 됩니다.

 

그러면 위 코드를 Builder pattern 을 사용해서 만들어 보겠습니다.

 

Builder.php
<?php
/**
* Created by PhpStorm.
* User: naya
* Date: 2020/04/24
* Time: 9:17 AM
*/
namespace Naya\parse\site\test;
class Builder
{
private $url;
private $refer;
private $agent;
public function build(): Parsing {
return new Parsing($this);
}
/**
* @return mixed
*/
public function getAgent() {
return $this->agent;
}
/**
* @return mixed
*/
public function getRefer() {
return $this->refer;
}
/**
* @return mixed
*/
public function getUrl() {
return $this->url;
}
/**
* @param mixed $agent
*/
public function setAgent($agent) {
$this->agent = $agent;
return $this;
}
/**
* @param mixed $refer
*/
public function setRefer($refer) {
$this->refer = $refer;
return $this;
}
/**
* @param mixed $url
*/
public function setUrl($url) {
$this->url = $url;
return $this;
}
}

 

 

Parsing.php
<?php
/**
* Created by PhpStorm.
* User: naya
* Date: 2020/04/24
* Time: 9:18 AM
*/
namespace Naya\parse\site\test;
class Parsing
{
private $url;
private $refer;
private $agent;
public function __construct(Builder $builder) {
$this->url = $builder->getUrl();
$this->refer = $builder->getRefer();
$this->agent = $builder->getAgent();
}
static public function createBuilder(): Builder {
return new Builder();
}
/**
* @return mixed
*/
public function getUrl() {
return $this->url;
}
/**
* @return mixed
*/
public function getRefer() {
return $this->refer;
}
/**
* @return mixed
*/
public function getAgent() {
return $this->agent;
}
}

 

 

<?php
/**
* Created by PhpStorm.
* User: naya
* Date: 2020/04/24
* Time: 9:18 AM
*/
require __DIR__ . '/../vendor/autoload.php';
use Naya\parse\site\test\Parsing;
use Naya\parse\site\test\Builder;
$config = Parsing::createBuilder()
->setUrl("url")
->setAgent("agent")
->setRefer("refer")
->build();
echo '<pre>';
print_r($config);
<pre>Naya\parse\site\test\Parsing Object
(
[url:Naya\parse\site\test\Parsing:private] => url
[refer:Naya\parse\site\test\Parsing:private] => refer
[agent:Naya\parse\site\test\Parsing:private] => agent
)

 

이제 $config->get 메소드를 이용해서 실제 사용할 코드에서 사용하면 됩니다.

코드 내용이 많아지는것 같지만 사용하는 코드에서는 많은 부분에서 깔끔해집니다.

제가 사용하는 코드중에서 더 좋은 코드 있으시면 많은 조언 부탁드립니다.