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.