프로그래밍/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 메소드를 이용해서 실제 사용할 코드에서 사용하면 됩니다.

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

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