เมื่อออกแบบรหัสคุณมีสองตัวเลือก
- เพิ่งจะทำมันเสร็จแล้วซึ่งในกรณีนี้การแก้ปัญหาใด ๆ ก็จะใช้ได้ผลสำหรับคุณ
- เป็นคนคล่องแคล่วและออกแบบโซลูชั่นที่ใช้ประโยชน์จากนิสัยใจคอของภาษาและอุดมการณ์ของมัน (ภาษา OO ในกรณีนี้ - การใช้ polymorphism เป็นเครื่องมือในการตัดสินใจ)
ฉันจะไม่มุ่งความสนใจไปที่หนึ่งในสองคนแรกเพราะไม่มีอะไรจะพูด หากคุณแค่อยากให้มันใช้งานได้คุณสามารถทิ้งรหัสไว้ได้
แต่จะเกิดอะไรขึ้นถ้าคุณเลือกที่จะทำแบบอวดความคิดและแก้ไขปัญหากับรูปแบบการออกแบบในแบบที่คุณต้องการ
คุณสามารถดูกระบวนการต่อไปนี้:
เมื่อออกแบบรหัส OO ส่วนใหญ่if
ที่อยู่ในรหัสไม่จำเป็นต้องอยู่ที่นั่น โดยธรรมชาติหากคุณต้องการเปรียบเทียบสองประเภทสเกลาร์เช่นint
s หรือfloat
s คุณมีโอกาสที่จะมีif
แต่ถ้าคุณต้องการเปลี่ยนขั้นตอนตามการกำหนดค่าคุณสามารถใช้polymorphismเพื่อบรรลุสิ่งที่คุณต้องการย้ายการตัดสินใจ ( if
s) จากเหตุผลทางธุรกิจของคุณไปยังสถานที่ที่วัตถุ instantiated - เพื่อโรงงาน
ณ ตอนนี้กระบวนการของคุณสามารถผ่าน 4 เส้นทางแยก:
data
ไม่มีการเข้ารหัสหรือบีบอัด (โทรอะไรกลับมาdata
)
data
ถูกบีบอัด (โทรcompress(data)
และส่งคืน)
data
ถูกเข้ารหัส (โทรencrypt(data)
และส่งคืน)
data
ถูกบีบอัดและเข้ารหัส (โทรencrypt(compress(data))
แล้วส่งคืน)
เพียงแค่มองไปที่ 4 เส้นทางคุณจะพบปัญหา
คุณมีหนึ่งกระบวนการที่เรียก 3 (ในทางทฤษฎี 4 ถ้าคุณนับว่าไม่เรียกอะไรเป็นหนึ่ง) วิธีการต่าง ๆ ที่จัดการข้อมูลแล้วส่งคืน เมธอดมีชื่อแตกต่างกันเรียกว่าพับลิก API สาธารณะ (วิธีที่วิธีการสื่อสารพฤติกรรมของพวกเขา)
การใช้รูปแบบอะแดปเตอร์เราสามารถแก้ไขชื่อ colision (เราสามารถรวม API สาธารณะ) ที่เกิดขึ้นได้ กล่าวง่ายๆว่าอะแดปเตอร์ช่วยให้อินเตอร์เฟสที่เข้ากันไม่ได้ทั้งสองทำงานร่วมกันได้ นอกจากนี้อะแดปเตอร์ยังทำงานด้วยการกำหนดอินเทอร์เฟซของอะแดปเตอร์ใหม่ซึ่งคลาสที่พยายามรวมการใช้ API ของตนเข้าด้วยกัน
นี่ไม่ใช่ภาษาที่เป็นรูปธรรม มันเป็นวิธีการทั่วไปคำหลักใด ๆ ที่มีเพื่อแสดงว่าอาจเป็นรูปแบบใด ๆ ในภาษาเช่น C # คุณสามารถแทนที่ด้วย generics ( <T>
)
ฉันจะสมมติว่าตอนนี้คุณสามารถมีสองคลาสที่รับผิดชอบการบีบอัดและการเข้ารหัส
class Compression
{
Compress(data : any) : any { ... }
}
class Encryption
{
Encrypt(data : any) : any { ... }
}
ในโลกธุรกิจแม้แต่คลาสที่เฉพาะเจาะจงเหล่านี้มีแนวโน้มที่จะถูกแทนที่ด้วยอินเทอร์เฟซเช่นclass
คำหลักจะถูกแทนที่ด้วยinterface
(คุณควรจัดการกับภาษาเช่น C #, Java และ / หรือ PHP) หรือclass
คำหลักจะยังคงอยู่Compress
และEncrypt
วิธีการที่จะถูกกำหนดเป็นเสมือนจริงคุณควรรหัสใน C ++
ในการสร้างอะแดปเตอร์เรากำหนดอินเตอร์เฟสทั่วไป
interface DataProcessing
{
Process(data : any) : any;
}
จากนั้นเราจะต้องจัดทำอินเทอร์เฟซให้มีประโยชน์
// when neither encryption nor compression is enabled
class DoNothingAdapter : DataProcessing
{
public Process(data : any) : any
{
return data;
}
}
// when only compression is enabled
class CompressionAdapter : DataProcessing
{
private compression : Compression;
public Process(data : any) : any
{
return this.compression.Compress(data);
}
}
// when only encryption is enabled
class EncryptionAdapter : DataProcessing
{
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(data);
}
}
// when both, compression and encryption are enabled
class CompressionEncryptionAdapter : DataProcessing
{
private compression : Compression;
private encryption : Encryption;
public Process(data : any) : any
{
return this.encryption.Encrypt(
this.compression.Compress(data)
);
}
}
ด้วยการทำเช่นนี้คุณจะจบลงด้วย 4 คลาสซึ่งแต่ละคนทำสิ่งที่แตกต่างกันโดยสิ้นเชิง แต่แต่ละคลาสก็มี API สาธารณะเดียวกัน Process
วิธี
ในตรรกะทางธุรกิจของคุณที่คุณจัดการกับการตัดสินใจที่ไม่มี / การเข้ารหัส / การบีบอัด / ทั้งสองคุณจะออกแบบวัตถุของคุณเพื่อให้มันขึ้นอยู่กับDataProcessing
อินเทอร์เฟซที่เราออกแบบมาก่อน
class DataService
{
private dataProcessing : DataProcessing;
public DataService(dataProcessing : DataProcessing)
{
this.dataProcessing = dataProcessing;
}
}
กระบวนการนั้นอาจจะง่ายอย่างนี้:
public ComplicatedProcess(data : any) : any
{
data = this.dataProcessing.Process(data);
// ... perhaps work with the data
return data;
}
ไม่มีเงื่อนไขเพิ่มเติม ชั้นDataService
ไม่มีความคิดว่าจะทำอย่างไรกับข้อมูลจริง ๆ เมื่อมันถูกส่งไปยังdataProcessing
สมาชิกและไม่สนใจจริง ๆ มันเป็นความรับผิดชอบของมัน
เป็นการดีที่คุณจะมีการทดสอบหน่วยการทดสอบ 4 ชั้นอะแดปเตอร์ที่คุณสร้างขึ้นเพื่อให้แน่ใจว่าพวกเขาทำงานคุณทำแบบทดสอบของคุณ และถ้าพวกเขาผ่านคุณสามารถมั่นใจได้ว่าพวกเขาจะทำงานไม่ว่าคุณจะเรียกพวกเขาในรหัสของคุณ
ดังนั้นทำอย่างนี้ฉันจะไม่if
อยู่ในรหัสของฉันอีกต่อไป?
ไม่คุณมีโอกาสน้อยที่จะมีเงื่อนไขในตรรกะทางธุรกิจของคุณ แต่พวกเขายังคงต้องอยู่ที่ไหนซักแห่ง สถานที่คือโรงงานของคุณ
และนี่คือสิ่งที่ดี คุณแยกความกังวลของการสร้างและใช้รหัสจริง หากคุณทำให้โรงงานของคุณเชื่อถือได้ (ใน Java คุณสามารถใช้งานได้กับ Google เช่นกรอบการทำงานของGuice ) ในตรรกะทางธุรกิจของคุณคุณไม่ต้องกังวลกับการเลือกชั้นเรียนที่ถูกต้อง เพราะคุณรู้ว่าโรงงานของคุณทำงานและจะส่งมอบสิ่งที่ถูกถาม
จำเป็นต้องมีคลาสอินเทอร์เฟซและอื่น ๆ ทั้งหมดหรือไม่
สิ่งนี้นำเรากลับไปสู่จุดเริ่มต้น
ใน OOP หากคุณเลือกเส้นทางที่จะใช้ polymorphism ต้องการใช้รูปแบบการออกแบบต้องการใช้ประโยชน์จากคุณสมบัติของภาษาและ / หรือต้องการทำตามทุกอย่างเป็นอุดมการณ์ของวัตถุ และจากนั้นตัวอย่างนี้ไม่ได้แสดงโรงงานทั้งหมดที่คุณต้องการและถ้าคุณต้องปรับโครงสร้างCompression
และEncryption
คลาสและทำให้อินเทอร์เฟซแทนคุณต้องรวมการใช้งานของพวกเขาด้วย
ในท้ายที่สุดคุณจะได้พบกับคลาสและอินเตอร์เฟสขนาดเล็กหลายร้อยรายการโดยมุ่งเน้นที่สิ่งที่เฉพาะเจาะจงมาก ซึ่งไม่จำเป็นต้องเลวร้ายใด ๆ แต่อาจไม่ใช่วิธีที่ดีที่สุดสำหรับคุณหากคุณต้องการเพียงทำบางอย่างง่ายๆเช่นการเพิ่มตัวเลขสองตัว
หากคุณต้องการที่จะได้รับมันกระทำได้อย่างรวดเร็วและคุณสามารถคว้าแก้ปัญหา Ixrec ของที่อย่างน้อยมีการจัดการที่จะกำจัดelse if
และบล็อกซึ่งในความคิดของฉันแม้ตาดเลวร้ายยิ่งกว่าธรรมดาelse
if
คำนึงถึงนี่เป็นวิธีของฉันในการออกแบบ OO ที่ดี การเข้ารหัสไปยังอินเทอร์เฟซมากกว่าการนำไปใช้งานนี่เป็นวิธีที่ฉันทำในช่วงไม่กี่ปีที่ผ่านมาและเป็นวิธีที่ฉันคุ้นเคยกับมันมากที่สุด
ฉันชอบการเขียนโปรแกรมแบบ if-less มากขึ้นและจะซาบซึ้งมากขึ้นถึงวิธีแก้ปัญหาที่ยาวกว่ารหัส 5 บรรทัด มันเป็นวิธีที่ฉันคุ้นเคยกับการออกแบบโค้ดและฉันอ่านมันได้อย่างสบายใจ
อัปเดต 2:มีการพูดคุยอย่างฉับพลันเกี่ยวกับโซลูชันเวอร์ชันแรกของฉัน การสนทนาส่วนใหญ่เกิดจากฉันซึ่งฉันขอโทษ
ฉันตัดสินใจที่จะแก้ไขคำตอบในลักษณะที่เป็นวิธีหนึ่งในการดูวิธีแก้ไขปัญหา แต่ไม่ใช่วิธีเดียว ฉันยังลบส่วนมัณฑนากรซึ่งฉันหมายถึงส่วนหน้าแทนซึ่งในที่สุดฉันก็ตัดสินใจแยกออกอย่างสมบูรณ์เพราะอะแดปเตอร์เป็นรูปแบบด้านหน้า
if
คำสั่งใหม่หรือไม่?