ความแตกต่างระหว่างรูปแบบ Bridge และ Adapter คืออะไร?
ความแตกต่างระหว่างรูปแบบ Bridge และ Adapter คืออะไร?
คำตอบ:
"อะแดปเตอร์ทำให้สิ่งต่างๆใช้งานได้หลังจากออกแบบสะพานทำให้ใช้งานได้ก่อนที่จะเป็น [GoF, p219]"
อย่างมีประสิทธิภาพรูปแบบอะแดปเตอร์มีประโยชน์เมื่อคุณมีรหัสที่มีอยู่ไม่ว่าจะเป็นของบุคคลที่สามหรือในองค์กร แต่ไม่สามารถควบคุมได้หรือไม่สามารถเปลี่ยนแปลงได้เพื่อให้ตรงตามอินเทอร์เฟซที่คุณต้องการ ตัวอย่างเช่นเรามี SuperWeaponsArray ซึ่งสามารถควบคุมอุปกรณ์วันโลกาวินาศได้
public class SuperWeaponsArray {
/*...*/
public void destroyWorld() {
for (Weapon w : armedWeapons) {
w.fire();
}
}
}
ยิ่งใหญ่ ยกเว้นเราตระหนักว่าเรามีอุปกรณ์นิวเคลียร์ในคลังแสงของเราซึ่งมีมาก่อนการแปลงเป็นอินเทอร์เฟซ Weapon แต่เราอยากให้มันทำงานที่นี่จริงๆ ... แล้วเราจะทำยังไง ... ลิ่มเข้าไป!
NukeWeaponsAdaptor - อิงจากคลาส Nuke ของเรา แต่ส่งออกอินเทอร์เฟซ Weapon น่ารักตอนนี้เราสามารถทำลายโลกได้อย่างแน่นอน ดูเหมือนจะเป็นเศษเล็กเศษน้อย แต่ก็ทำให้สิ่งต่างๆทำงานได้ดี
สะพานรูปแบบเป็นสิ่งที่คุณใช้ขึ้นด้านหน้า - ถ้าคุณรู้ว่าคุณมีสองลำดับชั้นมุมฉากก็มีวิธีการแยกอินเตอร์เฟซและการดำเนินการในลักษณะดังกล่าวที่คุณไม่ได้รับจำนวนบ้าของชั้นเรียน สมมติว่าคุณมี:
ประเภท MemoryMappedFile และ DirectReadFile ของอ็อบเจ็กต์ไฟล์ สมมติว่าคุณต้องการอ่านไฟล์จากแหล่งต่างๆ (อาจใช้ Linux เทียบกับการใช้งาน Windows ฯลฯ ) Bridge ช่วยให้คุณหลีกเลี่ยงการคดเคี้ยวด้วย:
หน่วยความจำแมป Windows หน่วยความจำไฟล์แมปลินุกซ์ไฟล์โดยตรงอ่าน Windows ไฟล์โดยตรงอ่านลินุกซ์ไฟล์
http://en.wikipedia.org/wiki/Adapter_pattern
รูปแบบอะแดปเตอร์เป็นข้อมูลเพิ่มเติมเกี่ยวกับการทำให้โค้ดที่มีอยู่ของคุณทำงานกับระบบหรืออินเทอร์เฟซที่ใหม่กว่า
หากคุณมีชุด API บริการเว็บมาตรฐานของ บริษัท ที่คุณต้องการเสนอให้กับอินเทอร์เฟซการขยายความสามารถที่มีอยู่ของแอปพลิเคชันอื่นคุณอาจพิจารณาเขียนชุดอะแดปเตอร์เพื่อดำเนินการนี้ โปรดทราบว่ามีพื้นที่สีเทาและเป็นข้อมูลเพิ่มเติมเกี่ยวกับวิธีการกำหนดรูปแบบในทางเทคนิคเนื่องจากรูปแบบอื่น ๆ เช่นส่วนหน้าจะคล้ายกัน
http://en.wikipedia.org/wiki/Bridge_pattern
รูปแบบ Bridge จะช่วยให้คุณสามารถใช้อัลกอริทึมหรือระบบทางเลือกอื่นได้
แม้ว่าจะไม่ใช่ตัวอย่างรูปแบบ Bridge แบบคลาสสิก แต่ลองนึกดูว่าคุณมีการใช้งานที่เก็บข้อมูลบางส่วนหรือไม่: อันหนึ่งมีประสิทธิภาพในพื้นที่ส่วนอีกแบบมีประสิทธิภาพในด้านดิบ ... และคุณมีกรณีทางธุรกิจสำหรับนำเสนอทั้งในแอปหรือเฟรมเวิร์กของคุณ .
สำหรับคำถามของคุณ "ฉันจะใช้รูปแบบไหนได้ที่ไหน" คำตอบคือทุกที่ที่เหมาะสมสำหรับโครงการของคุณ! อาจพิจารณาเสนอการแก้ไขคำชี้แจงเพื่อเป็นแนวทางในการอภิปรายเกี่ยวกับจุดที่คุณเชื่อว่าคุณต้องใช้อย่างใดอย่างหนึ่ง
อะแดปเตอร์:
UML Diagram:จากบทความdofactory :
Target : กำหนดอินเทอร์เฟซเฉพาะโดเมนที่ไคลเอ็นต์ใช้
Adapter : ปรับอินเทอร์เฟซ Adaptee กับอินเทอร์เฟซ Target
Adaptee : กำหนดอินเทอร์เฟซที่มีอยู่ซึ่งจำเป็นต้องปรับเปลี่ยน
ไคลเอนต์ : ทำงานร่วมกับอ็อบเจ็กต์ที่สอดคล้องกับอินเทอร์เฟซ Target
ตัวอย่าง:
สี่เหลี่ยมจัตุรัสและสี่เหลี่ยมผืนผ้าเป็นรูปทรงที่แตกต่างกันสองรูปแบบและการหาพื้นที่ () ของแต่ละรูปแบบต้องใช้วิธีการที่แตกต่างกัน แต่ยังคง Square ทำงานบนอินเทอร์เฟซสี่เหลี่ยมผืนผ้าพร้อมการแปลงคุณสมบัติบางอย่าง
public class AdapterDemo{
public static void main(String args[]){
SquareArea s = new SquareArea(4);
System.out.println("Square area :"+s.getArea());
}
}
class RectangleArea {
public int getArea(int length, int width){
return length * width;
}
}
class SquareArea extends RectangleArea {
int length;
public SquareArea(int length){
this.length = length;
}
public int getArea(){
return getArea(length,length);
}
}
สะพาน:
แก้ไข: (ตามคำแนะนำของ @quasoft)
คุณมีองค์ประกอบสี่ส่วนในรูปแบบนี้
Abstraction : เป็นการกำหนดอินเทอร์เฟซ
RefinedAbstraction : ใช้นามธรรม:
Implementor : กำหนดอินเทอร์เฟซสำหรับการนำไปใช้งาน
ConcreteImplementor : ใช้อินเทอร์เฟซ Implementor
ข้อมูลโค้ด:
Gear gear = new ManualGear();
Vehicle vehicle = new Car(gear);
vehicle.addGear();
gear = new AutoGear();
vehicle = new Car(gear);
vehicle.addGear();
โพสต์ที่เกี่ยวข้อง:
คุณใช้ Bridge Pattern เมื่อใด แตกต่างจากรูปแบบ Adapter อย่างไร?
ความแตกต่างที่สำคัญ:จากsourcemakingบทความ
กระทู้นี้มีมาสักพักแล้ว อย่างไรก็ตามสิ่งสำคัญคือต้องเข้าใจว่าส่วนหน้านั้นค่อนข้างคล้ายกับอะแดปเตอร์ แต่ก็ไม่เหมือนกัน อะแด็ปเตอร์ "ปรับ" คลาสที่มีอยู่ให้เป็นคลาสไคลเอนต์ที่เข้ากันไม่ได้ สมมติว่าคุณมีระบบเวิร์กโฟลว์เก่าที่แอปพลิเคชันของคุณใช้เป็นไคลเอนต์ บริษัท ของคุณอาจแทนที่ระบบเวิร์กโฟลว์ด้วยระบบใหม่ที่ "เข้ากันไม่ได้" (ในแง่ของอินเทอร์เฟซ) ในกรณีส่วนใหญ่คุณสามารถใช้รูปแบบอะแด็ปเตอร์และเขียนโค้ดที่เรียกใช้อินเทอร์เฟซของกลไกเวิร์กโฟลว์ใหม่ได้ โดยทั่วไปสะพานมักใช้ในลักษณะที่แตกต่างกัน หากคุณมีระบบที่ต้องทำงานกับระบบไฟล์อื่น (เช่นโลคัลดิสก์ NFS เป็นต้น) คุณสามารถใช้รูปแบบบริดจ์และสร้างเลเยอร์นามธรรมหนึ่งชั้นเพื่อทำงานกับระบบไฟล์ทั้งหมดของคุณ โดยพื้นฐานแล้วจะเป็นกรณีการใช้งานที่เรียบง่ายสำหรับรูปแบบสะพาน Facade และอะแดปเตอร์ใช้คุณสมบัติบางอย่างร่วมกัน แต่โดยปกติ facades จะใช้เพื่อลดความซับซ้อนของอินเทอร์เฟซ / คลาสที่มีอยู่ ในช่วงแรก ๆ ของ EJB ไม่มีการเรียกร้องให้ EJB ในท้องถิ่น นักพัฒนามักจะได้รับต้นขั้วโดยย่อให้แคบลงและเรียกมันว่า "หลอกจากระยะไกล" บ่อยครั้งนี้ทำให้เกิดปัญหาด้านประสิทธิภาพ (โดยเฉพาะเมื่อเรียกผ่านสายไฟจริงๆ) นักพัฒนาที่มีประสบการณ์จะใช้รูปแบบด้านหน้าเพื่อจัดเตรียมอินเทอร์เฟซที่หยาบมากให้กับลูกค้า จากนั้นซุ้มนี้จะทำการเรียกหลายครั้งไปยังวิธีการแบบละเอียดที่แตกต่างกัน สรุปแล้วสิ่งนี้ช่วยลดจำนวนการเรียกเมธอดที่ต้องการลงอย่างมากและเพิ่มประสิทธิภาพ
Bridge ได้รับการปรับปรุง Adapter Bridge มีอะแดปเตอร์และเพิ่มความยืดหยุ่นเพิ่มเติมให้กับมัน องค์ประกอบจากแผนผังคำตอบของ Ravindra ระหว่างรูปแบบมีดังนี้
Adapter | Bridge
-----------|---------------
Target | Abstraction
-----------|---------------
| RefinedAbstraction
|
| This element is Bridge specific. If there is a group of
| implementations that share the same logic, the logic can be placed here.
| For example, all cars split into two large groups: manual and auto.
| So, there will be two RefinedAbstraction classes.
-----------|---------------
Adapter | Implementor
-----------|---------------
Adaptee | ConcreteImplementor
ในคำตอบด้านบน @James อ้างอิงประโยคจาก GoF หน้า 219 ฉันคิดว่ามันคุ้มค่าที่จะอธิบายคำอธิบายทั้งหมดที่นี่
อะแดปเตอร์เทียบกับบริดจ์
รูปแบบอะแดปเตอร์และบริดจ์มีคุณลักษณะทั่วไปบางประการ ทั้งสองส่งเสริมความยืดหยุ่นโดยให้ระดับของทิศทางไปยังวัตถุอื่น ทั้งสองเกี่ยวข้องกับการส่งต่อคำขอไปยังวัตถุนี้จากอินเทอร์เฟซอื่นที่ไม่ใช่ของตัวเอง
ความแตกต่างที่สำคัญระหว่างรูปแบบเหล่านี้อยู่ที่ความตั้งใจ Adapter มุ่งเน้นไปที่การแก้ไขปัญหาความเข้ากันไม่ได้ระหว่างสองอินเทอร์เฟซที่มีอยู่ ไม่ได้มุ่งเน้นไปที่วิธีการใช้งานอินเทอร์เฟซเหล่านั้นและไม่พิจารณาว่าอินเทอร์เฟซเหล่านั้นจะมีวิวัฒนาการอย่างอิสระอย่างไร เป็นวิธีการทำให้คลาสที่ออกแบบอย่างอิสระสองคลาสทำงานร่วมกันโดยไม่ต้องนำคลาสใดคลาสหนึ่งมาใช้ซ้ำ ในทางกลับกัน Bridge เชื่อมโยงสิ่งที่เป็นนามธรรมและการนำไปใช้งาน (อาจมีจำนวนมาก) มันให้อินเทอร์เฟซที่เสถียรแก่ลูกค้าแม้ว่าจะช่วยให้คุณสามารถเปลี่ยนคลาสที่ใช้งานได้ นอกจากนี้ยังรองรับการใช้งานใหม่ ๆ เมื่อระบบพัฒนาขึ้น
จากความแตกต่างเหล่านี้จึงมักใช้ Adapter และ Bridge ในจุดที่ต่างกันในวงจรชีวิตซอฟต์แวร์ บ่อยครั้งที่อะแด็ปเตอร์จำเป็นเมื่อคุณพบว่าคลาสที่เข้ากันไม่ได้สองคลาสควรทำงานร่วมกันโดยทั่วไปเพื่อหลีกเลี่ยงการจำลองโค้ด การมีเพศสัมพันธ์เป็นสิ่งที่คาดไม่ถึง ในทางตรงกันข้ามผู้ใช้สะพานเข้าใจล่วงหน้าว่าสิ่งที่เป็นนามธรรมต้องมีการใช้งานหลายอย่างและทั้งสองอย่างอาจพัฒนาอย่างอิสระ รูปแบบอะแดปเตอร์ทำให้สิ่งต่างๆทำงานได้หลังจากออกแบบแล้ว บริดจ์ทำให้พวกเขาทำงานก่อนที่จะเป็น นั่นไม่ได้หมายความว่า Adapter ด้อยกว่า Bridge อย่างใด แต่ละรูปแบบเป็นเพียงการแก้ไขปัญหาที่แตกต่างกัน
สมมติว่าคุณมีคลาส Shape นามธรรมที่มีฟังก์ชันการวาดภาพ (ทั่วไป / นามธรรม) และวงกลมที่ใช้ Shape รูปแบบสะพานเป็นวิธีนามธรรมสองทางในการแยกการใช้งาน (การวาดในวงกลม) และฟังก์ชันทั่วไป / นามธรรม (การวาดภาพในคลาส Shape)
แท้จริงแล้วหมายความว่าอย่างไร? เมื่อมองแวบแรกดูเหมือนสิ่งที่คุณทำไปแล้ว (โดยการผกผันการพึ่งพา) จึงไม่ต้องกังวลเกี่ยวกับการมีฐานรหัสโมดูลาร์ที่มีจำนวนน้อยกว่าหรือมากกว่า แต่เป็นปรัชญาที่ลึกซึ้งกว่านั้นเล็กน้อย
จากความเข้าใจของฉันความต้องการของรูปแบบการใช้งานอาจเกิดขึ้นเมื่อฉันต้องการเพิ่มคลาสใหม่ที่เกี่ยวข้องอย่างใกล้ชิดกับระบบปัจจุบัน (เช่น RedCircle หรือ GreenCircle) และแตกต่างกันเพียงฟังก์ชันเดียว (เช่นสี) และฉันจะต้องใช้รูปแบบ Bridge โดยเฉพาะอย่างยิ่งหากมีการเปลี่ยนแปลงคลาสของระบบที่มีอยู่ (วงกลมหรือรูปร่าง) บ่อยๆและคุณไม่ต้องการให้คลาสที่เพิ่มใหม่ได้รับผลกระทบจากการเปลี่ยนแปลงเหล่านั้น นั่นคือเหตุผลที่ฟังก์ชันการวาดภาพทั่วไปถูกนำไปรวมไว้ในอินเทอร์เฟซใหม่เพื่อให้คุณสามารถปรับเปลี่ยนพฤติกรรมการวาดโดยไม่ขึ้นกับรูปร่างหรือวงกลม
ดูเหมือนคำตอบที่สั้นและชัดเจนสำหรับฉันตามคำตอบ stackoverflow อื่นที่นี่ :
อะแดปเตอร์ถูกใช้เมื่อคุณมีอินเทอร์เฟซนามธรรมและคุณต้องการแมปอินเทอร์เฟซนั้นกับอ็อบเจ็กต์อื่นที่มีบทบาทการทำงานคล้ายกัน แต่เป็นอินเทอร์เฟซที่แตกต่างกัน
Bridgeคล้ายกับ Adapter มาก แต่เราเรียกมันว่า Bridge เมื่อคุณกำหนดทั้งอินเทอร์เฟซนามธรรมและการนำไปใช้งาน กล่าวคือคุณไม่ได้ปรับให้เข้ากับรหัสเดิมหรือรหัสของบุคคลที่สามคุณเป็นผู้ออกแบบโค้ดทั้งหมด แต่คุณต้องสามารถสลับการใช้งานที่แตกต่างกันได้