PHP에서 팩토리 디자인 패턴이란 무엇입니까?


88

이것은 가장 간단한 용어로 무엇을 하는가? 당신이 당신의 어머니 또는 누군가에게 거의 기쁘게 설명하고 있다고 가정하십시오.


115
어머니는 어차피 이해하지 못하셨을 것입니다 ...
Bruno Reis

6
@JasonDavis 계속 질문에 답하고 있습니다 ... 스토커가 된 기분이 들기 시작했습니다.
Tyler Carter

답변:


175

팩토리는 객체를 생성합니다. 그래서 당신이 만들고 싶다면

 class A{
    public $classb;
    public $classc;
    public function __construct($classb, $classc)
    {
         $this->classb = $classb;
         $this->classc = $classc;
    }
  }

객체를 만들 때마다 다음 코드를 수행해야하는 것에 의존하고 싶지 않을 것입니다.

$obj = new ClassA(new ClassB, new Class C);

그것이 공장이 들어오는 곳입니다. 우리는 그것을 처리 할 공장을 정의합니다.

class Factory{
    public function build()
    {
        $classc = $this->buildC();
        $classb = $this->buildB();
        return $this->buildA($classb, $classc);

    }

    public function buildA($classb, $classc)
    {
        return new ClassA($classb, $classc);
    }

    public function buildB()
    {
        return new ClassB;
    }

    public function buildC()
    {
        return new ClassC;
    }
}

이제 우리가해야 할 일은

$factory = new Factory;
$obj     = $factory->build();

진짜 장점은 클래스를 바꾸고 싶을 때입니다. 다른 ClassC를 전달하고 싶다고 가정 해 보겠습니다.

class Factory_New extends Factory{
    public function buildC(){
        return new ClassD;
    }
}

또는 새로운 ClassB :

class Factory_New2 extends Factory{
    public function buildB(){
        return new ClassE;
    }
}

이제 상속을 사용하여 클래스 생성 방법을 쉽게 수정하여 다른 클래스 집합에 넣을 수 있습니다.

좋은 예는 다음 사용자 클래스 일 수 있습니다.

class User{
    public $data;
    public function __construct($data)
    {
        $this->data = $data;
    }
}

이 클래스 $data는 데이터를 저장하는 데 사용하는 클래스입니다. 이제이 클래스에 대해 세션을 사용하여 데이터를 저장한다고 가정 해 보겠습니다. 공장은 다음과 같습니다.

class Factory{
    public function build()
    {
        $data = $this->buildData();
        return $this->buildUser($data);
    }

    public function buildData()
    {
        return SessionObject();
    }

    public function buildUser($data)
    {
        return User($data);
    }
}

이제 데이터베이스에 모든 데이터를 저장하고 싶다고 가정 해 보겠습니다. 변경하는 것은 정말 간단합니다.

class Factory_New extends Factory{
    public function buildData()
    {
        return DatabaseObject();
    }
}

팩토리는 개체를 조립하는 방법을 제어하는 ​​데 사용하는 디자인 패턴이며 올바른 팩토리 패턴을 사용하면 필요한 사용자 지정 개체를 만들 수 있습니다.


3
그것은 많은 타이핑이었습니다. 이제 나는 어느 시점에서 그것을 내 위키에 올려야 할 것입니다.
Tyler Carter

1
훌륭하고 도움이되었습니다. 당신에게 모자를 벗고 짝.
stefgosselin

1
코드의 차이 / 이점은 무엇입니까 $obj = $factory->build();이상 $obj = new whateverClass();? 또한 classA의 데이터에 의존하는 다른 클래스 (예 : classZ)에서, classZ에서 팩토리 메서드를 사용 하시겠습니까? 기본적으로 클래스 (classA) 내에서 클래스 (classZ)를 인스턴스화하고 있으며 이는 테스트가 없음을 의미합니다. 예를 들어 팩토리 new는 단지를 사용하는 대신 메소드를 통해 수행 할 코드로드 인 것 같습니다 new.
James

19

실제 공장처럼 무언가를 만들어 반환합니다.

이런 걸 상상 해봐

$joe = new Joe();
$joe->say('hello');

또는 공장 방법

Joe::Factory()->say('hello');

팩토리 메서드의 구현은 새 인스턴스를 만들고 반환합니다.


1
좋은 예는이 패턴에 대한 구현이 얼마나 다양한 지 놀랍습니다. 정적으로 호출되면 나중에 동일한 인스턴스를 재사용하기 위해 인스턴스에 대한 참조를 얻을 수 있다고 가정합니다. 즉 $ joe = Joe :: Factory ()-> say ( 'hello');
stefgosselin

확실히 5.6에서와 마찬가지로 (new Joe ())-> say ( 'hello');
Pancho

13

여러 리소스를 처리하고 높은 수준의 추상화를 구현하려는 경우 팩토리 디자인 패턴이 매우 좋습니다.

이것을 다른 섹션으로 나누자.

추상화를 구현해야하고 클래스 사용자가 클래스 정의에서 구현 한 것에 대해 신경 쓸 필요가 없다고 가정합니다.

그 / 그녀는 클래스 메소드 사용에 대해 걱정할 필요가 있습니다.

예 : 프로젝트에 대해 두 개의 데이터베이스가 있습니다.

class MySQLConn {

        public function __construct() {
                echo "MySQL Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your mysql select query execute here" . PHP_EOL;
        }

}

class OracleConn {

        public function __construct() {
                echo "Oracle Database Connection" . PHP_EOL;
        }

        public function select() {
                echo "Your oracle select query execute here" . PHP_EOL;
        }

}

Factory 클래스는 데이터베이스 연결을위한 객체 생성을 처리합니다.

class DBFactory {

        public static function getConn($dbtype) {

                switch($dbtype) {
                        case "MySQL":
                                $dbobj = new MySQLConn();
                                break;
                        case "Oracle":
                                $dbobj = new OracleConn();
                                break;
                        default:
                                $dbobj = new MySQLConn();
                                break;
                }

                return $dbobj;
        }

}

사용자는 데이터베이스 유형의 이름 만 전달하면됩니다.

$dbconn1 = DBFactory::getConn("MySQL");
$dbconn1->select();

산출:

MySQL Database Connection
Your mysql select query execute here

미래에는 다른 데이터베이스가있을 수 있으며 전체 코드를 변경할 필요가 없습니다. 새 데이터베이스 유형을 전달하기 만하면 다른 코드는 변경없이 실행됩니다.

$dbconn2 = DBFactory::getConn("Oracle");
$dbconn2->select();

산출:

Oracle Database Connection
Your oracle select query execute here

이것이 도움이되기를 바랍니다.


1

일반적으로 "공장"은 무언가를 생성합니다. 객체 지향 프로그래밍의 경우 "공장 설계 패턴"은 객체를 생성합니다.

PHP, C # 또는 기타 객체 지향 언어인지는 중요하지 않습니다.


1

Factory Design Pattern (Factory Pattern)은 느슨한 결합을위한 것입니다. 공장의 의미와 같이 최종 사용자에게 공장 (데이터 생산)으로 데이터를 보냅니다. 이러한 방식으로 공장은 데이터 소스와 데이터 프로세스 간의 긴밀한 결합을 해제합니다.



0

이 답변은 Daniel White가 공장 패턴을 사용하여 MySQL 연결을 생성하기 위해 공장을 사용한다고 말한 다른 게시물과 관련이 있습니다.

MySQL 연결의 경우 데이터베이스에 액세스하는 데 다른 연결을 생성하지 않고 동일한 연결을 사용하기를 원하므로 싱글 톤 패턴을 사용합니다.


0

개체를 인스턴스화하는 고전적인 접근 방식은 다음과 같습니다.

$Object=new ClassName();

PHP에는 다음 구문을 사용하여 변수 이름에서 객체를 동적으로 생성하는 기능이 있습니다.

$Object=new $classname;

여기서 $ classname 변수에는 인스턴스화하려는 클래스 이름이 포함됩니다.

따라서 고전적인 개체 인수 분해는 다음과 같습니다.

function getInstance($classname)
{
  if($classname==='Customer')
  {
    $Object=new Customer();
  }
  elseif($classname==='Product')
  {
    $Object=new Product();
  }
  return $Object;
}

getInstance ( 'Product') 함수를 호출하면이 팩토리가 Product 객체를 생성하고 반환합니다. 그렇지 않으면 getInstance ( 'Customer') 함수를 호출하면이 팩토리는 Customer () 클래스에서 생성 된 Customer 유형 개체를 만들고 반환합니다.

더 이상 그럴 필요가 없습니다. 동적 인스턴스화를위한 변수 값으로 'Product'또는 'Customer'(기존 클래스의 정확한 이름)를 보낼 수 있습니다.

$classname='Product';
$Object1=new $classname; //this will instantiate new Product()

$classname='Customer';
$Object2=new $classname; //this will instantiate new Customer()

0

간단히 말해서 @Pindatjuh와 같은 공장은 객체를 반환합니다.

그렇다면 생성자와의 차이점은 무엇입니까? (동일합니다)

  1. 생성자는 자신의 인스턴스를 사용합니다.
  2. 내가 원하는 것보다 더 발전된 것을 원하고 객체를 부풀 리거나 종속성을 추가하고 싶지 않습니다.
  3. 생성자는 각 인스턴스가 생성 될 때 호출됩니다. 때때로 당신은 그것을 원하지 않습니다.

    예를 들어 Account 클래스의 객체를 만들 때마다 데이터베이스에서 파일을 읽어 템플릿으로 사용한다고 가정 해 보겠습니다.

생성자 사용 :

class Account {
      var $user;
      var $pwd;
      var ...
      public __construct() {
         // here i read from the file
         // and many other stuff
      }
}

공장 사용 :

class Account {
      var $user;
      var $pwd;
      var ...
}
class AccountFactory {
      public static Create() {
         $obj=new Account();
         // here we read the file and more stuff.
         return $obj;
      }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.