รูปแบบการออกแบบโรงงานใน PHP คืออะไร?


90

สิ่งนี้ทำให้ฉันสับสนในแง่ที่ง่ายที่สุดมันทำอะไร? แสร้งทำเป็นว่าคุณกำลังอธิบายให้แม่ของคุณหรือใครบางคนฟัง


116
แม่คงไม่เข้าใจอยู่ดี ...
Bruno Reis

6
@JasonDavis ฉันยังคงตอบคำถามของคุณ ... ฉันเริ่มรู้สึกเหมือนเป็นสตอล์กเกอร์
Tyler Carter

คำตอบ:


176

โรงงานสร้างวัตถุ ดังนั้นหากคุณต้องการสร้าง

 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
นั่นคือการพิมพ์จำนวนมาก ตอนนี้ฉันจะต้องวางไว้ใน wiki ของฉันในบางจุด
Tyler Carter

1
ดีและเป็นประโยชน์ สวมหมวกให้คุณ
stefgosselin

1
อะไรคือความแตกต่าง / ประโยชน์ของรหัสของคุณ$obj = $factory->build();มากกว่า$obj = new whateverClass();? นอกจากนี้ในคลาสอื่น (เช่น classZ) ซึ่งขึ้นอยู่กับข้อมูลของ classA คุณจะใช้วิธีการโรงงานที่ไหนใน classZ โดยพื้นฐานแล้วคุณยังคงสร้างอินสแตนซ์คลาส (classZ) ภายในคลาส (classA) ซึ่งหมายความว่าไม่มีการทดสอบ เช่นโรงงานดูเหมือนจะเป็นโหลดโค้ดที่ต้องทำnewด้วยวิธีการแทนที่จะใช้เพียงnewอย่างเดียว
James

นี่คือความสับสนสำหรับฉัน ฉันอ่านเกี่ยวกับโรงงานและผู้สร้างมาหลายชั่วโมงแล้วและดูเหมือนว่าจะเป็นผู้สร้างไม่ใช่โรงงาน
akinuri

19

เหมือนโรงงานในชีวิตจริงมันสร้างบางอย่างและส่งคืนมัน

ลองนึกภาพแบบนี้

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

หรือวิธีการโรงงาน

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

การดำเนินการตามวิธีการของโรงงานจะสร้างอินสแตนซ์ใหม่และส่งคืน


1
ตัวอย่างที่ดีทำให้ฉันประหลาดใจว่าการใช้งานรูปแบบนี้มีความหลากหลายเพียงใด เมื่อเรียกแบบคงที่ฉันคิดว่าเราสามารถรับการอ้างอิงถึงอินสแตนซ์เพื่อนำอินสแตนซ์เดียวกันมาใช้ใหม่ในภายหลังได้หรือไม่? เช่น $ joe = Joe :: Factory () -> say ('hello');
stefgosselin

แน่นอนที่ 5.6 เราสามารถทำได้ (โจใหม่ ()) -> พูด ('สวัสดี');
Pancho

15

รูปแบบการออกแบบโรงงานเป็นสิ่งที่ดีมากเมื่อคุณต้องจัดการกับทรัพยากรหลายอย่างและต้องการใช้นามธรรมระดับสูง

มาแบ่งเป็นส่วนต่างๆกัน

สมมติว่าคุณต้องใช้สิ่งที่เป็นนามธรรมและผู้ใช้ในชั้นเรียนของคุณไม่จำเป็นต้องสนใจเกี่ยวกับสิ่งที่คุณได้นำไปใช้ในนิยามชั้นเรียน

เขา / เธอต้องกังวลเกี่ยวกับการใช้วิธีการเรียนของคุณ

เช่นคุณมีสองฐานข้อมูลสำหรับโครงการของคุณ

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

โดยทั่วไป "โรงงาน" จะผลิตบางสิ่งบางอย่าง: ในกรณีของ Object-Orientated-Programming "รูปแบบการออกแบบโรงงาน" จะผลิตวัตถุ

ไม่สำคัญว่าจะเป็น PHP, C # หรือภาษาเชิงวัตถุอื่น ๆ


1

รูปแบบการออกแบบโรงงาน (รูปแบบโรงงาน) ใช้สำหรับการต่อแบบหลวม เช่นเดียวกับความหมายของโรงงานข้อมูลโรงงาน (ผลิตข้อมูล) ไปยังผู้ใช้ขั้นสุดท้าย ด้วยวิธีนี้โรงงานจะทำลายการมีเพศสัมพันธ์ที่แน่นหนาระหว่างแหล่งข้อมูลและกระบวนการของข้อมูล



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 ('ผลิตภัณฑ์') โรงงานนี้จะสร้างและส่งคืนวัตถุผลิตภัณฑ์ มิฉะนั้นหากคุณเรียกใช้ฟังก์ชัน getInstance ('ลูกค้า') โรงงานนี้จะสร้างและส่งคืนอ็อบเจ็กต์ประเภทลูกค้า (สร้างจากคลาส 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. ตัวสร้างถูกเรียกเมื่อแต่ละอินสแตนซ์ถูกสร้างขึ้น บางครั้งคุณไม่ต้องการสิ่งนั้น

    ตัวอย่างเช่นสมมติว่าทุกครั้งที่ฉันสร้างออบเจ็กต์ของบัญชีคลาสฉันอ่านไฟล์จากฐานข้อมูลและใช้เป็นเทมเพลต

ใช้ตัวสร้าง:

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.