PHP'de Fabrika Tasarım Modeli nedir?


90

Bu kafamı karıştırıyor, en basit terimlerle ne işe yarıyor? Annenize ya da neredeyse lütfen birine açıklıyormuşsunuz gibi yapın.


116
Annem zaten anlamazdı ...
Bruno Reis

6
@JasonDavis Sorularınıza cevap vermeye devam ediyorum ... Bir takipçi gibi hissetmeye başlıyorum.
Tyler Carter

Yanıtlar:


176

Bir fabrika bir nesne yaratır. Yani, inşa etmek istersen

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

Nesneyi her oluşturduğunuzda aşağıdaki kodu yapmak zorunda olduğunuza güvenmek istemezsiniz

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

Fabrikanın devreye gireceği yer burasıdır. Bunu bizim için halledecek bir fabrika tanımlarız:

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;
    }
}

Şimdi tek yapmamız gereken

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

Asıl avantaj, sınıfı değiştirmek istediğiniz zamandır. Farklı bir ClassC'yi geçmek istediğimizi varsayalım:

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

veya yeni bir ClassB:

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

Artık, sınıfın nasıl oluşturulduğunu kolayca değiştirmek, farklı bir sınıf kümesi eklemek için kalıtımı kullanabiliriz.

İyi bir örnek bu kullanıcı sınıfı olabilir:

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

Bu sınıfta $dataverilerimizi saklamak için kullandığımız sınıftır. Şimdi bu sınıf için, verilerimizi depolamak için bir Oturum kullandığımızı varsayalım. Fabrika şöyle görünecektir:

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

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

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

Şimdi, bunun yerine tüm verilerimizi veritabanında saklamak istediğimizi varsayalım, onu değiştirmek gerçekten çok kolay:

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

Fabrikalar, nesneleri nasıl bir araya getireceğimizi kontrol etmek için kullandığımız bir tasarım modelidir ve doğru fabrika kalıplarını kullanmak, ihtiyacımız olan özelleştirilmiş nesneleri oluşturmamızı sağlar.


3
Bu çok yazı yazmaktı. Şimdi bir noktada onu wiki'me koymam gerekecek.
Tyler Carter

1
Güzel ve yardımsever. Sana şapka çıkar dostum.
stefgosselin

1
Kodunuzun farkı / faydası nedir $obj = $factory->build();üzerinde $obj = new whateverClass();? Ayrıca, sınıfA'nın verilerine bağlı olan başka bir sınıfta (örneğin classZ), classZ'de fabrika yöntemini nerede kullanırsınız? Esasen hâlâ bir sınıf (classA) içinde bir sınıfın (classZ) örneğini oluşturuyorsunuz, bu da test olmadığı anlamına gelir. Örneğin fabrika new, sadece kullanmak yerine bir yöntem aracılığıyla yapılacak bir kod yükü gibi görünüyor new.
James

Bu benim için kafa karıştırıcı. Geçen bir saattir fabrikalar ve inşaatçılar hakkında okuyorum ve bu bir fabrika değil, bir inşaatçı gibi görünüyor.
akinuri

19

Gerçek hayattaki bir fabrika gibi, bir şey yaratır ve onu iade eder.

Bunun gibi bir şey hayal edin

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

veya bir fabrika yöntemi

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

Fabrika yönteminin uygulanması yeni bir örnek oluşturur ve onu döndürür.


1
Güzel örnek, bu model için uygulamaların ne kadar çeşitli olduğunu beni şaşırtıyor. Statik olarak çağrıldığında, aynı örneği daha sonra yeniden kullanmak için örneğe bir referans alınabileceğini varsayıyorum. yani $ joe = Joe :: Factory () -> say ('merhaba');
stefgosselin

kesinlikle 5.6'da olduğu gibi (new Joe ()) -> say ('merhaba');
Pancho

15

Birden fazla kaynakla uğraşırken ve yüksek düzeyde soyutlama uygulamak istediğinizde fabrika tasarım modeli çok iyidir.

Bunu farklı bölüme ayıralım.

Soyutlamayı uygulamanız gerektiğini ve sınıfınızın kullanıcısının sınıf tanımında neyi uyguladığınızı umursamadığını varsayalım.

Sadece sınıf yöntemlerinin kullanımı konusunda endişelenmesi gerekiyor.

Örneğin, projeniz için iki veritabanınız var

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 sınıfınız, veritabanı bağlantısı için nesnenin yaratılmasıyla ilgilenir.

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;
        }

}

Kullanıcının sadece veritabanı türünün adını geçmesi gerekir

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

Çıktı:

MySQL Database Connection
Your mysql select query execute here

Gelecekte farklı bir veritabanınız olabilir, bu durumda tüm kodu değiştirmeniz gerekmez, yalnızca yeni veritabanı türünü geçmeniz gerekir ve diğer kod herhangi bir değişiklik yapmadan çalışır.

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

Çıktı:

Oracle Database Connection
Your oracle select query execute here

Umarım bu yardımcı olur.


1

Genel olarak bir "fabrika" bir şey üretir: Nesne Yönelimli Programlama durumunda, "fabrika tasarım modeli" nesneler üretir.

PHP, C # veya başka bir Nesne Yönelimli dilde olması önemli değil.


1

Fabrika Tasarım Modeli (Fabrika Modeli) gevşek bağlantı içindir. Fabrikanın anlamı gibi, bir fabrikaya veri (veri üretir) son kullanıcıya kadar. Bu şekilde fabrika, veri kaynağı ile veri işlemi arasındaki sıkı bağlantıyı keser.



0

Bu cevap, Daniel White'ın fabrika modelini kullanarak MySQL bağlantısı oluşturmak için fabrikayı kullanacağını söylediği diğer gönderiyle ilgilidir.

MySQL bağlantısı için, başka bir tane oluşturmak yerine veritabanına erişmek için aynı bağlantıyı kullanmak istediğiniz için tekli model kullanmayı tercih ederim.


0

Bir nesneyi somutlaştırmak için klasik yaklaşım şudur:

$Object=new ClassName();

PHP, aşağıdaki sözdizimini kullanarak değişken adından dinamik olarak bir nesne oluşturma yeteneğine sahiptir:

$Object=new $classname;

$ sınıfadı değişkeni, örneklenmek istenen sınıfın adını içerir.

Dolayısıyla klasik nesne çarpanlarına ayırma şöyle görünür:

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

ve getInstance ('Ürün') işlevini çağırırsanız, bu fabrika Ürün nesnesini oluşturacak ve iade edecektir. Aksi takdirde, getInstance ('Müşteri') işlevini çağırırsanız, bu fabrika Müşteri türü nesnesini (Customer () sınıfından oluşturulan) oluşturur ve döndürür.

Artık buna gerek yok, dinamik örnekleme için değişken değeri olarak "Ürün" veya "Müşteri" (mevcut sınıfların tam adları) gönderilebilir:

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

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

0

Kayıt için, basit bir deyişle, @ Pindatjuh'un dediği gibi bir fabrika bir nesne döndürür.

Öyleyse, bir kurucunun farkı nedir? (aynı şeyi yapar)

  1. bir kurucu kendi örneğini kullanır.
  2. Çok daha gelişmiş bir şey yapmak istediğim bir şey ve nesneyi şişirmek (veya bağımlılıklar eklemek) istemiyorum.
  3. Yapıcı, her örnek oluşturulduğunda çağrılır. Bazen bunu istemezsin.

    Örneğin, Account sınıfına ait bir nesneyi her oluşturduğumda, veritabanından bir dosya okuyup şablon olarak kullandığımı varsayalım.

Yapıcıyı kullanma:

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

Fabrikayı kullanma:

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;
      }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.