PHP: การสร้าง ID ที่ไม่ซ้ำกับคลาสที่ไม่ได้จำลอง

สมมติว่าฉันต้องการมีชุดของวัตถุ ซึ่งแต่ละชุดควรมี ID เฉพาะของตัวเอง ไม่จำเป็นต้องมีอะไรหรูหรา แค่ตัวอักษรที่ระบุว่าเป็นวัตถุประเภทใด และตัวเลขที่ระบุว่าวัตถุเหล่านี้ถูกสร้างขึ้นมากี่ชิ้น เช่น a0, a1, b0, c0, c1, c2, c3 และอื่นๆ

แทนที่จะตั้งค่าตัวแปรโกลบอลเพื่อติดตามจำนวนอ็อบเจ็กต์แต่ละรายการที่มีอยู่แล้ว ฉันต้องการดำเนินการดังกล่าวกับคลาส ชอบเช่นนั้น:

class uniqueIDGenerator
{
  private $numberAObjs;
  private $numberBObjs;
  private $numberCObjs;

  public function generateID ($type) {
    if($type === "A") {
      return 'a' . (int) $this->$numberAObjs++;
    } else if($type === "B") {
      return 'b' . (int) $this->$numberBObjs++;
    } else if($type === "C") {
        return 'c' . (int) $this->$numberCObjs++;
    }
  }
}

class obj
{
  private $id;

  function __construct($type) {
    $this->id = uniqueIDGenerator::generateID($type);
  }
}

ปัญหาก็คือว่าหาก UniqueIDGenerator ไม่ได้เกิดขึ้นจริง ฟังก์ชัน GenerateID ของมันจะส่งคืนค่าเดียวกันสำหรับแต่ละประเภทเสมอ (เช่น a0, b0, c0 เป็นต้น) เนื่องจากตัวแปรส่วนตัวไม่ได้ถูกสร้างขึ้นในหน่วยความจำจริงๆ ในเวลาเดียวกัน การทำให้คุณสมบัติของ obj จะไม่ทำงาน เพราะทุกครั้งที่สร้าง obj มันจะมีอินสแตนซ์ของ IDGenerator ของตัวเอง ดังนั้นมันจะคืนค่า a0, b0, c0 เสมอ (สมมติว่ามันเรียกว่าเท่านั้น ครั้งเดียวในวิธีการของวัตถุนั้น) และอื่นๆ

ดูเหมือนว่าตัวเลือกเดียวคือการทำให้ UniqueIDGenerator เป็นอินสแตนซ์ระดับโลกของตัวเองเพื่อให้ Constructor ของ obj สามารถอ้างอิงได้ แต่ดูเหมือนว่าจะมีการเขียนโค้ดที่ไม่ดี มีวิธี OOP ที่ดีในการทำเช่นนี้ที่แยกวัตถุทั้งหมดออกจากกันและจัดระเบียบหรือไม่?


person A. Duff    schedule 30.10.2013    source แหล่งที่มา
comment
คุณต้องจัดเก็บข้อมูลเป็นไฟล์: ไม่ว่าคุณจะเปิดไฟล์และเขียนรหัสหรือคุณใช้ระบบฐานข้อมูล (pgsql, mysql ฯลฯ...) และคุณต้องประกาศวิธีการของคุณ static   -  person Pierre Emmanuel Lallemant    schedule 30.10.2013
comment
ขอบคุณสำหรับคำติชม แต่นี่ไม่ได้ใช้กับเว็บแอป แต่เขียนด้วย PHP เท่านั้น นี่คือสคริปต์ PHP ที่จะรันครั้งเดียว อ่านข้อมูลจากไฟล์ และสร้างไฟล์เอาท์พุตซึ่งแต่ละอ็อบเจ็กต์ที่สร้างขึ้นจะต้องมีตัวระบุเฉพาะของตัวเอง   -  person A. Duff    schedule 30.10.2013
comment
คุณไม่สามารถสร้าง IDGenerator ที่เป็นเอกลักษณ์ของคุณสักครั้งได้หรือไม่? อา ฉันจะเขียนคำตอบที่เหมาะสม ;)   -  person Pierre Emmanuel Lallemant    schedule 30.10.2013
comment
วัตถุอยู่ในคลาสเดียวกันเสมอหรือไม่   -  person Ja͢ck    schedule 30.10.2013
comment
คุณอาจลองทำงานกับคอลเลกชัน พวกเขาสามารถติดตามจำนวนวัตถุที่สร้างขึ้น คุณอาจสร้างคอลเลกชันสำหรับแต่ละประเภทที่คุณต้องการสร้าง คอลเลกชันสามารถวนซ้ำวัตถุ คืนจำนวนวัตถุ ฯลฯ   -  person busypeoples    schedule 30.10.2013
comment
คำถามอื่นๆ: วัตถุจำเป็นต้องมีความรู้เกี่ยวกับรหัสเฉพาะหรือไม่ ข้อมูลจะไม่คงอยู่จากสิ่งที่ฉันเข้าใจ   -  person busypeoples    schedule 30.10.2013
comment
ใช่ วัตถุจะเป็นคลาสเดียวกันเสมอ ตามวิธีการเข้ารหัสในปัจจุบัน วัตถุควรทราบ ID ของตนเอง   -  person A. Duff    schedule 31.10.2013


คำตอบ (1)


ขั้นแรกคุณสามารถแก้ไขตัวสร้างวัตถุได้:

class obj
{
  private $id;

  function __construct($type, $id) {
    $this->id = $id;
  }
}

...

$id_generator = new uniqueIDGenerator(); // instanciation of the generator

$obj1 = new obj(type, $id_generator->generateID($type));
$obj2 = new obj(type, $id_generator->generateID($type));
$obj3 = new obj(type, $id_generator->generateID($type));
...

ในโครงการของฉัน ฉันจะสร้างคลาสชื่อ ObjectFactory:

    class ObjectFactory {
       private $id_generator;

       public function __construct($id_generator) {
          $this->id_generator = $id_generator;
       }

       public function create_object($type) {
          return new obj($this->id_generator->generateID($type));
       }
    }

...

$id_generator = new uniqueIDGenerator(); // instanciation of the generator
$obj_factory = new ObjectFactory($id_generator); 

$obj1 = obj_factory->create_object($type);
$obj2 = obj_factory->create_object($type);
$obj3 = obj_factory->create_object($type);

สุดท้ายนี้ เพื่อหลีกเลี่ยงการใช้อินสแตนซ์ระดับโลกของคลาสนี้ คุณสามารถทำ Singleton ได้ (ปรับให้เข้ากับสถานการณ์ของคุณ):

class uniqueIDGenerator
{
  private $numberAObjs;
  private $numberBObjs;
  private $numberCObjs;

  public static $instance = null;

  public function __construct() {
    $numberAObjs = 0;
    $numberBObjs = 0;
    $numberCObjs = 0;
  }

  public static function generateID($type) {
     if(!self::$instance)
        self::$instance = new uniqueIDGenerator();

     return self::$instance->generateID2($type);
  }

  private function generateID2 ($type) {
    if($type === "A") {
      return 'a' . (int) $this->numberAObjs++;
    } else if($type === "B") {
      return 'b' . (int) $this->numberBObjs++;
    } else if($type === "C") {
        return 'c' . (int) $this->numberCObjs++;
    }
  }
}

uniqueIDGenerator::generateID("A");
person Pierre Emmanuel Lallemant    schedule 30.10.2013
comment
ใช่ นั่นคือสิ่งที่ฉันกำลังพูด ทางเลือกเดียวที่ดูเหมือนจะทำให้มันเป็นอินสแตนซ์ระดับโลกของคลาสนั้น ฉันอาจจำเป็นต้องทำเช่นนั้น แค่สงสัยว่ามีวิธี OOP ที่ดีกว่าในการทำเช่นนี้เพื่อหลีกเลี่ยงการมีตัวแปรทั่วโลกหรือไม่ - person A. Duff; 30.10.2013
comment
อ่า รูปแบบโรงงานเป็นความคิดที่ดี ขอบคุณที่ชี้ให้ฉันไปในทิศทางนั้น - person A. Duff; 30.10.2013
comment
ฉันแก้ไขสองครั้ง คุณสามารถใช้รูปแบบการออกแบบซิงเกิลตันได้เช่นกัน (แก้ไขเล็กน้อยสำหรับกรณีของคุณ) ;) มันช่วยให้คุณหลีกเลี่ยงที่จะจัดเก็บอินสแตนซ์ระดับโลกให้กับตัวเอง - person Pierre Emmanuel Lallemant; 30.10.2013
comment
เอาล่ะ ขอบคุณสำหรับความช่วยเหลือทั้งหมด ชื่นชมมาก ปกติผมไม่เลือก Accepted Answer จนกว่าจะเปิดคำถามได้หนึ่งวัน เพียงเพื่อให้คนอื่นได้มีโอกาสแบ่งปันความรู้ให้มากที่สุด แต่ดูเหมือนผมจะแจกให้คุณพรุ่งนี้ - person A. Duff; 30.10.2013