ข้อดีและข้อเสียบางอย่าง
ข้อดีสำหรับ polymorphic:
- ส่วนต่อประสาน polymorphic ที่เล็กกว่านั้นง่ายต่อการอ่าน ฉันต้องจำวิธีเดียวเท่านั้น
- มันไปพร้อมกับวิธีการใช้ภาษา - การพิมพ์เป็ด
- ถ้ามันชัดเจนว่าวัตถุใดที่ฉันต้องการดึงกระต่ายออกมาก็ไม่ควรมีความกำกวมอยู่ดี
- การทำการตรวจสอบประเภทจำนวนมากถือว่าไม่ดีแม้ในภาษาแบบคงที่เช่น Java ซึ่งการตรวจสอบประเภทจำนวนมากสำหรับประเภทของวัตถุสร้างรหัสที่น่าเกลียดนักมายากลควรจะแยกแยะความแตกต่างระหว่างประเภทของวัตถุที่เขาดึงกระต่ายออกมา ?
ข้อดีสำหรับเฉพาะกิจ:
- มีความชัดเจนน้อยกว่าฉันสามารถดึงสตริงออกมาจาก
Cat
อินสแตนซ์ได้หรือไม่ มันจะใช้ได้ไหม ถ้าไม่ใช่พฤติกรรมคืออะไร? หากฉันไม่ จำกัด ประเภทที่นี่ฉันต้องทำในเอกสารหรือในการทดสอบที่อาจทำให้สัญญาแย่ลง
- คุณมีการจัดการกับการดึงกระต่ายในที่เดียวนักมายากล (บางคนอาจคิดว่านี่เป็นการต่อต้าน)
- เครื่องมือเพิ่มประสิทธิภาพ JS สมัยใหม่แตกต่างกันระหว่าง monomorphic (ทำงานกับประเภทเดียว) และฟังก์ชัน polymorphic พวกเขารู้วิธีที่จะเพิ่มประสิทธิภาพคน monomorphic มากดีกว่าดังนั้น
pullRabbitOutOfString
รุ่นมีแนวโน้มที่จะมากได้เร็วขึ้นในเครื่องมือเช่น V8 ดูวิดีโอนี้สำหรับข้อมูลเพิ่มเติม แก้ไข:ฉันเขียน perf ตัวเองปรากฎว่าในทางปฏิบัตินี่ไม่ใช่กรณีเสมอไป
ทางเลือกอื่น ๆ :
ในความคิดของฉันการออกแบบประเภทนี้ไม่ได้เป็น 'Java-Scripty' มากนัก JavaScript เป็นภาษาที่แตกต่างกันและมีสำนวนต่าง ๆ จากภาษาเช่น C #, Java หรือ Python สำนวนเหล่านี้เกิดขึ้นในหลายปีของนักพัฒนาที่พยายามเข้าใจส่วนที่อ่อนแอและแข็งแกร่งของภาษาสิ่งที่ฉันทำคือพยายามที่จะยึดติดกับสำนวนเหล่านี้
มีวิธีแก้ปัญหาที่ดีสองข้อที่ฉันนึกได้:
- การยกระดับวัตถุทำให้วัตถุ "ดึงได้" ทำให้วัตถุนั้นสอดคล้องกับอินเทอร์เฟซในเวลาทำงานจากนั้นให้นักมายากลทำงานบนวัตถุที่ดึงได้
- ใช้รูปแบบกลยุทธ์การสอนผู้วิเศษแบบไดนามิกวิธีการจัดการวัตถุชนิดต่าง ๆ
โซลูชันที่ 1: วัตถุที่ยกระดับ
ทางออกหนึ่งที่พบบ่อยในการแก้ไขปัญหานี้คือการ 'ยกระดับ' วัตถุด้วยความสามารถในการดึงกระต่ายออกมาจากพวกมัน
นั่นคือมีฟังก์ชั่นที่ใช้วัตถุบางชนิดและเพิ่มการดึงหมวกออกมา สิ่งที่ต้องการ:
function makePullable(obj){
obj.pullOfHat = function(){
return new Rabbit(obj.toString());
}
}
ฉันสามารถสร้างmakePullable
ฟังก์ชั่นดังกล่าวสำหรับวัตถุอื่นฉันสามารถสร้างmakePullableString
ฯลฯ ฉันกำหนดการแปลงในแต่ละประเภท อย่างไรก็ตามหลังจากที่ฉันยกระดับวัตถุของฉันฉันไม่มีประเภทที่จะใช้พวกเขาในทางทั่วไป อินเทอร์เฟซใน JavaScript ถูกกำหนดโดยการพิมพ์เป็ดหากมีpullOfHat
วิธีฉันสามารถดึงมันด้วยวิธีการของนักมายากล
จากนั้นนักมายากลก็สามารถทำได้:
Magician.pullRabbit = function(pullable) {
var rabbit = obj.pullOfHat();
return {rabbit:rabbit,text:"Tada, I pulled a rabbit out of "+pullable};
}
การยกระดับวัตถุโดยใช้รูปแบบมิกซ์อินบางประเภทดูเหมือนว่าจะต้องทำสิ่งเพิ่มเติมใน JS (โปรดทราบว่านี่เป็นปัญหากับประเภทค่าในภาษาซึ่งเป็นสตริง, จำนวน, null, ไม่ได้กำหนดและบูลีน แต่พวกมันทั้งหมดสามารถใช้กล่องได้)
นี่คือตัวอย่างของรหัสดังกล่าวที่อาจมีลักษณะเหมือน
โซลูชันที่ 2: รูปแบบกลยุทธ์
เมื่อพูดถึงคำถามนี้ในห้องแชท JS ใน StackOverflow เพื่อนของฉันphenomnomnominalแนะนำให้ใช้ของรูปแบบกลยุทธ์
สิ่งนี้จะช่วยให้คุณสามารถเพิ่มความสามารถในการดึงกระต่ายออกจากวัตถุต่าง ๆ ในขณะใช้งานและจะสร้างโค้ดจาวาสคริปต์ นักมายากลสามารถเรียนรู้วิธีการดึงวัตถุประเภทต่าง ๆ ออกมาจากหมวกและดึงพวกเขาตามความรู้นั้น
นี่คือลักษณะที่ปรากฏใน CoffeeScript:
class Magician
constructor: ()-> # A new Magician can't pull anything
@pullFunctions = {}
pullRabbit: (obj) -> # Pull a rabbit, handler based on type
func = pullFunctions[obj.constructor.name]
if func? then func(obj) else "Don't know how to pull that out of my hat!"
learnToPull: (obj, handler) -> # Learns to pull a rabbit out of a type
pullFunctions[obj.constructor.name] = handler
ท่านสามารถเข้าดูเทียบเท่ารหัส JS ที่นี่
ด้วยวิธีนี้คุณจะได้รับประโยชน์จากทั้งสองโลกการกระทำของวิธีการดึงไม่ได้เชื่อมโยงอย่างแน่นหนากับวัตถุหรือนักมายากลและฉันคิดว่านี่เป็นวิธีการแก้ปัญหาที่ดีมาก
การใช้งานจะเป็นสิ่งที่ชอบ:
var m = new Magician();//create a new Magician
//Teach the Magician
m.learnToPull("",function(){
return "Pulled a rabbit out of a string";
});
m.learnToPull({},function(){
return "Pulled a rabbit out of a Object";
});
m.pullRabbit(" Str");