การเพิ่มฟิลด์ในคลาสที่รันไทม์ - รูปแบบการออกแบบ


15

ลองนึกภาพลูกค้าของคุณต้องการที่จะมีความเป็นไปได้ที่จะเพิ่มคุณสมบัติใหม่ (เช่นสี) ให้กับผลิตภัณฑ์ใน eshop ของพวกเขาใน CMS ของพวกเขา

แทนที่จะมีคุณสมบัติเป็นฟิลด์:

class Car extends Product {
   protected String type;
   protected int seats;
}

คุณอาจจะทำสิ่งที่ชอบ:

class Product {
   protected String productName;
   protected Map<String, Property> properties;
}

class Property {
   protected String name;
   protected String value;
}

นั่นคือการสร้างระบบประเภทของตัวเองอยู่ด้านบนของระบบที่มีอยู่ ฉันรู้สึกเช่นนี้อาจเห็นได้ว่าเป็นการสร้างโดเมนเฉพาะหรือไม่?

วิธีนี้เป็นรูปแบบการออกแบบที่รู้จักหรือไม่? คุณจะแก้ปัญหาต่างกันหรือไม่? ฉันรู้ว่ามีภาษาที่ฉันสามารถเพิ่มเขตข้อมูลในรันไทม์ แต่สิ่งที่เกี่ยวกับฐานข้อมูล? คุณอยากจะเพิ่ม / แก้ไขคอลัมน์หรือใช้การ Someting ตามที่แสดงด้านบนหรือไม่

ขอขอบคุณสำหรับเวลาของคุณ :).



ไม่แน่ใจว่าคุณใช้ภาษาอะไร แต่ถ้าเป็น C # คุณสามารถใช้ประเภทไดนามิกซึ่งโดยทั่วไปจะเก็บ KVP ไว้ในพจนานุกรมเช่นเดียวกับสิ่งที่คุณกำลังทำกับผลิตภัณฑ์ คอลเลกชันเป็นคอลเลกชัน คุณจะไม่มีการพิมพ์ที่แข็งแกร่ง ฉันรู้ว่าคุณขอรูปแบบการออกแบบ แต่ฉันไม่คิดว่าคุณจะต้องการอะไรที่ซับซ้อนในการใช้ msdn.microsoft.com/en-us/magazine/gg598922.aspx
Tony

โทนี่: ฉันใช้ Java ที่นี่ แต่ลองคิดดูว่ามันหลอก ๆ :) C # อนุญาตให้ฉันคงวัตถุไดนามิกนั้นไว้ในฐานข้อมูลหรือไม่ ฉันสงสัยเพราะ databse จำเป็นต้องรู้โครงสร้างของข้อมูลล่วงหน้า
Filip

มีรูปแบบการออกแบบรัฐ a-la Gang-of-Four ซึ่งทำให้วัตถุดูเหมือนจะเปลี่ยนประเภทหรือระดับของมันในเวลาทำงาน ทางเลือกอื่น ๆ คือรูปแบบการออกแบบของนักสังเกตการณ์หรือรูปแบบการออกแบบพร็อกซี
Nikos M.

1
ทำไมไม่เพียงแค่ใช้ประเภทข้อมูลแผนที่? ในฐานข้อมูลนั้นอาจแสดงเป็น {id} + {id, key, value} หากคุณไม่ได้ขอประสิทธิภาพ
Shadows In Rain

คำตอบ:


4

ขอแสดงความยินดี! คุณเพิ่ง circumnavigated ภาษาการเขียนโปรแกรม / ระบบโลกประเภทมาถึงในอีกด้านหนึ่งของโลกจากที่คุณออกไป คุณได้ลงสู่ดินแดนแห่งภาษาไดนามิก / วัตถุต้นแบบที่มีพลวัต!

ภาษาแบบไดนามิกจำนวนมาก (เช่น JavaScript, PHP, Python) อนุญาตให้ขยายหรือเปลี่ยนคุณสมบัติของวัตถุที่รันไทม์

รูปแบบสุดขั้วนี้เป็นภาษาที่ใช้ต้นแบบเช่นSelfหรือ JavaScript พวกเขาไม่มีชั้นเรียนพูดอย่างเคร่งครัด คุณสามารถทำสิ่งต่าง ๆ ที่มีลักษณะเหมือนการเขียนโปรแกรมแบบใช้คลาสเป็นเชิงวัตถุที่มีการสืบทอด แต่กฎมีความผ่อนคลายอย่างมากเมื่อเทียบกับภาษาที่ใช้ในคลาสที่กำหนดไว้อย่างคมชัดเช่น Java และ C #

Langauges เช่น PHP และ Python อาศัยอยู่ในพื้นที่ตรงกลาง พวกมันมีระบบคลาสพื้นฐานที่ใช้สำนวน แต่คุณสามารถเพิ่มเปลี่ยนแปลงหรือลบแอตทริบิวต์ของวัตถุได้ในขณะใช้งาน - แม้ว่าจะมีข้อ จำกัด บางอย่าง (เช่น "ยกเว้นชนิดในตัว") ที่คุณไม่พบใน JavaScript

ข้อดีข้อเสียของพลวัตนี้คือประสิทธิภาพ ลืมว่าภาษาที่พิมพ์อย่างรุนแรงหรืออ่อนแอหรือถูกรวบรวมลงในเครื่องได้ดีเพียงใด วัตถุแบบไดนามิกจะต้องแสดงเป็นแผนที่ / พจนานุกรมที่ยืดหยุ่นแทนที่จะเป็นแบบง่าย เพิ่มค่าใช้จ่ายในการเข้าถึงวัตถุทุกครั้ง บางโปรแกรมมีความยาวที่ยอดเยี่ยมเพื่อลดค่าใช้จ่ายนี้ (เช่นการกำหนด phantom kwarg และคลาสสล็อตตาม Python) แต่ค่าใช้จ่ายเพิ่มเติมมักจะเป็นค่าสำหรับหลักสูตรและราคาของการรับสมัคร

กลับไปที่การออกแบบของคุณคุณกำลังรับสินบนความสามารถในการมีคุณสมบัติแบบไดนามิกในส่วนย่อยของชั้นเรียนของคุณ Productสามารถมีแอตทริบิวต์ตัวแปร; น่าจะเป็นInvoiceหรือOrderจะและไม่สามารถ มันไม่ใช่วิธีที่เลวร้าย มันให้ความยืดหยุ่นแก่คุณในการมีรูปแบบที่คุณต้องการในขณะที่ยังคงอยู่ในระบบภาษาและระเบียบวินัยที่เข้มงวด คุณต้องรับผิดชอบในการจัดการคุณสมบัติที่ยืดหยุ่นเหล่านั้นและคุณอาจต้องดำเนินการผ่านกลไกที่ดูแตกต่างจากแอตทริบิวต์ดั้งเดิมมากกว่าเล็กน้อย p.prop('tensile_strength')มากกว่าp.tensile_strengthตัวอย่างเช่นและp.set_prop('tensile_strength', 104.4)มากกว่าp.tensile_strength = 104.4. แต่ฉันได้ทำงานกับและสร้างโปรแกรมจำนวนมากใน Pascal, Ada, C, Java และแม้แต่ภาษาแบบไดนามิกที่ใช้การเข้าถึง getter-setter อย่างแน่นอนสำหรับประเภทแอตทริบิวต์ที่ไม่ได้มาตรฐาน วิธีการนั้นสามารถใช้การได้อย่างชัดเจน

โดยโดยความตึงเครียดระหว่างประเภทคงที่และโลกที่แตกต่างกันนี้เป็นเรื่องธรรมดามาก มักพบปัญหาแบบอะนาล็อกเมื่อออกแบบสคีมาฐานข้อมูลโดยเฉพาะอย่างยิ่งสำหรับที่เก็บข้อมูลเชิงสัมพันธ์และข้อมูลเชิงสัมพันธ์ล่วงหน้า บางครั้งมันเกี่ยวข้องกับการสร้าง "แถวพิเศษ" ที่มีความยืดหยุ่นเพียงพอที่จะ จำกัด หรือกำหนดการรวมกันของรูปแบบที่จินตนาการทั้งหมดจากนั้นบรรจุข้อมูลใด ๆ ที่เข้ามาในเขตข้อมูลเหล่านั้น WordPress wp_postsตารางตัวอย่างเช่นมีเขตข้อมูลเช่นcomment_count, ping_status, post_parentและpost_date_gmtที่มีเฉพาะที่น่าสนใจภายใต้สถานการณ์บางและว่าในทางปฏิบัติมักจะไปว่างเปล่า อีกวิธีคือตารางที่ธรรมดาwp_optionsมาก ๆ เหมือนกับของคุณPropertyชั้น แม้ว่ามันจะต้องมีการจัดการที่ชัดเจนมากขึ้นรายการในนั้นจะไม่ค่อยว่าง ฐานข้อมูลเชิงวัตถุและเอกสาร (เช่น MongoDB) มักจะมีเวลาจัดการกับตัวเลือกการเปลี่ยนแปลงได้ง่ายขึ้นเพราะพวกเขาสามารถสร้างและตั้งค่าคุณลักษณะที่ต้องการได้


0

ฉันชอบคำถามสองเซ็นต์ของฉัน:

สองแนวทางของคุณแตกต่างอย่างสิ้นเชิง:

  • คนแรกคือ OO และพิมพ์อย่างมาก - แต่ไม่สามารถขยายได้
  • อย่างที่สองคือพิมพ์อย่างอ่อน (สตริง encapsulate อะไร)

ใน C ++ หลายคนจะใช้ std :: map of boost :: variantเพื่อให้ได้ทั้งสองอย่าง

ความผิดปกติ: โปรดทราบว่าบางภาษาเช่น C # อนุญาตการสร้างประเภทแบบไดนามิก ซึ่งอาจเป็นทางออกที่ดีสำหรับปัญหาทั่วไปในการเพิ่มสมาชิกแบบไดนามิก อย่างไรก็ตามประเภท "การแก้ไข / การเพิ่ม" หลังจากการคอมไพล์ทำให้ระบบประเภทนั้นเสียหายและทำให้ประเภท "การแก้ไข" ของคุณแทบจะไร้ประโยชน์ (เช่นคุณจะเข้าถึงคุณสมบัติที่เพิ่มเข้ามาได้อย่างไรเนื่องจากคุณไม่รู้ด้วยซ้ำว่ามันมีอยู่จริง) เป็นภาพสะท้อนที่เป็นระบบสำหรับแต่ละวัตถุ ... ลงท้ายด้วยภาษาไดนามิกบริสุทธิ์ _ คุณสามารถอ้างถึงคำสำคัญ 'ไดนามิก'. NET)


การสร้างประเภทที่รันไทม์ตะเข็บน่าสนใจ แต่แปลกใหม่เกินไปสำหรับฉัน (ฉันกำลังเขียนโปรแกรมใน Java) วิธีการแก้ปัญหาดังกล่าวจะไม่ทำงานถ้าฉันต้องการเก็บวัตถุใน databse ซึ่งเป็นประเภทที่ผมขอเชื่อเสมอ วิธีแก้ปัญหาที่พิมพ์ได้อย่างอ่อนแอที่ฉันเสนอสามารถเก็บไว้ในฐานข้อมูลได้อย่างง่ายดาย
Filip

0

การสร้างชนิดที่รันไทม์ฟังดูมีความซับซ้อนมากกว่านั้นเพียงแค่สร้างเลเยอร์ที่เป็นนามธรรม เป็นเรื่องธรรมดามากที่จะสร้างสิ่งที่เป็นนามธรรมให้กับระบบแยก

ให้ฉันแสดงตัวอย่างจากการปฏิบัติของฉัน แลกเปลี่ยนมอสโกมีแกนการค้าที่เรียกว่า Plaza2 พร้อม API ของผู้ค้า ผู้ค้าเขียนโปรแกรมเพื่อทำงานกับข้อมูลทางการเงิน ปัญหาคือข้อมูลนี้มีขนาดใหญ่มากซับซ้อนและเปิดเผยอย่างมากต่อการเปลี่ยนแปลง สามารถเปลี่ยนแปลงได้หลังจากผลิตภัณฑ์ทางการเงินใหม่เปิดตัวหรือรอการเปลี่ยนล้าง ไม่สามารถทำนายลักษณะของการเปลี่ยนแปลงในอนาคตได้ แท้จริงแล้วมันสามารถเปลี่ยนแปลงได้ทุกวันและโปรแกรมเมอร์ผู้น่าสงสารควรแก้ไขโค้ดและปล่อยเวอร์ชั่นใหม่และผู้ค้าที่โกรธควรแก้ไขระบบของพวกเขา

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

กลับไปที่ตัวอย่างของคุณเป็นเรื่องปกติที่จะสร้างภาษานามธรรมต่อหน้าตรรกะบางอย่าง อาจเป็น "คุณสมบัติ", "ตาราง", "ข้อความ" หรือแม้แต่ภาษามนุษย์ แต่ให้ความสนใจกับข้อเสียของวิธีการนี้:

  • รหัสเพิ่มเติมสำหรับการแยกวิเคราะห์และตรวจสอบความถูกต้อง (และหลักสูตรเพิ่มเติมเวลาปิด) ทุกสิ่งที่คอมไพเลอร์ทำเพื่อคุณด้วยการพิมพ์แบบคงที่คุณต้องทำในเวลาทำงาน
  • เอกสารเพิ่มเติมของข้อความตารางหรือสิ่งพื้นฐานอื่น ๆ ความซับซ้อนทั้งหมดเริ่มจากรหัสไปยัง schema หรือรูปแบบบางส่วน นี่คือตัวอย่างของ schema นรกทางการเงินดังกล่าวข้างต้น: http://ftp.moex.com/pub/FORTS/Plaza2/p2gate_en.pdf (หลายสิบหน้าของตาราง)

0

วิธีนี้เป็นรูปแบบการออกแบบที่รู้จักหรือไม่?

ใน XML และ HTML สิ่งเหล่านี้จะเป็นคุณสมบัติของโหนด / องค์ประกอบ ฉันเคยได้ยินพวกเขาเรียกว่าคุณสมบัติเพิ่มเติมคู่ชื่อ / ค่าและพารามิเตอร์

คุณจะแก้ปัญหาต่างกันหรือไม่?

นั่นคือวิธีที่ฉันจะแก้ปัญหาใช่

ฉันรู้ว่ามีภาษาที่ฉันสามารถเพิ่มเขตข้อมูลในรันไทม์ แต่สิ่งที่เกี่ยวกับฐานข้อมูล?

ฐานข้อมูลจะเหมือนกับจาวาในบางแง่มุม ใน pesudo-sql:

TABLE products
(
    product_name VARCHAR(50),
    product_id INTEGER AUTOINCREMENT
)

TABLE attributes
(
    product_id INTEGER,
    name VARCHAR(50),
    value VARCHAR(2000)
)

สิ่งนี้จะสอดคล้องกับ Java

class Product {
   protected String productName;
   protected Map<String, String> properties;
}

โปรดทราบว่าไม่จำเป็นต้องมีคลาส Property เนื่องจาก Map จัดเก็บชื่อเป็นคีย์

คุณอยากจะเพิ่ม / แก้ไขคอลัมน์หรือใช้การ Someting ตามที่แสดงด้านบนหรือไม่

ฉันลองเพิ่ม / แก้ไขคอลัมน์แล้วและมันก็เป็นฝันร้าย มันสามารถทำได้ แต่สิ่งต่าง ๆ ยังคงซิงค์และฉันไม่เคยได้รับมันทำงานได้ดี โครงสร้างตารางที่ฉันระบุไว้ด้านบนประสบความสำเร็จมากกว่า หากคุณจำเป็นต้องดำเนินการค้นหาและสั่งซื้อโดยพิจารณาใช้แอตทริบิวต์ตารางสำหรับแต่ละประเภทข้อมูล ( date_attributes, currency_attributesฯลฯ ) หรือการเพิ่มบางส่วนของคุณสมบัติเป็นคอลัมน์ฐานข้อมูลเก่าที่ดีในตารางผลิตภัณฑ์ รายงานมักจะเขียนลงในคอลัมน์ฐานข้อมูลได้ง่ายกว่าจากนั้นจึงย่อยตาราง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.