คลาส / เมธอดนามธรรมล้าสมัยหรือไม่?


37

ฉันเคยสร้างคลาส / วิธีการที่เป็นนามธรรมจำนวนมาก จากนั้นฉันก็เริ่มใช้อินเตอร์เฟส

ตอนนี้ฉันไม่แน่ใจว่าอินเทอร์เฟซไม่ทำให้คลาสนามธรรมล้าสมัยหรือไม่

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

ดังนั้นคลาส / เมธอด abstract ล้าสมัยหรือไม่?


ถ้าภาษาการเขียนโปรแกรมที่คุณเลือกไม่รองรับอินเตอร์เฟส? ฉันดูเหมือนจะจำได้ว่าเป็นกรณีของ C ++
เบอร์นาร์ด

7
@Bernard: ใน C ++ คลาสนามธรรมเป็นอินเตอร์เฟสทั้งหมดยกเว้นชื่อ การที่พวกเขาสามารถทำมากกว่า 'บริสุทธิ์' อินเทอร์เฟซไม่เสียเปรียบ
gbjbaanb

@gbjbaanb: ฉันคิดว่า ฉันจำไม่ได้ว่าใช้พวกเขาเป็นอินเทอร์เฟซ แต่ให้การใช้งานเริ่มต้น
เบอร์นาร์ด

อินเทอร์เฟซคือ "สกุลเงิน" ของการอ้างอิงวัตถุ โดยทั่วไปการพูดพวกเขาเป็นพื้นฐานของพฤติกรรม polymorphic คลาสนามธรรมมีจุดประสงค์ที่แตกต่างกันซึ่งเดดอลนิกซ์อธิบายได้อย่างสมบูรณ์แบบ
jiggy

4
นี่ไม่เหมือนกับการพูดว่า "โหมดการขนส่งล้าสมัยแล้วตอนนี้เรามีรถยนต์หรือไม่" ใช่แล้วคุณใช้รถยนต์เป็นส่วนใหญ่ แต่ไม่ว่าคุณจะต้องการอะไรนอกเหนือจากรถหรือไม่ก็ตามมันจะไม่ถูกต้องที่จะพูดว่า "ฉันไม่ต้องการใช้โหมดการขนส่ง" อินเทอร์เฟซเหมือนกับคลาสนามธรรมโดยไม่มีการใช้งานใด ๆ และมีชื่อพิเศษไม่?
แจ็ค V.

คำตอบ:


111

เลขที่

อินเทอร์เฟซไม่สามารถให้เริ่มต้นใช้งานคลาสนามธรรมและวิธีสามารถ นี่เป็นประโยชน์โดยเฉพาะอย่างยิ่งเพื่อหลีกเลี่ยงการทำสำเนารหัสในหลายกรณี

นี่เป็นวิธีที่ดีมากในการลดการเชื่อมต่อตามลำดับ หากไม่มีเมธอด / คลาส abstract คุณไม่สามารถใช้รูปแบบเมธอดเทมเพลตได้ ฉันขอแนะนำให้คุณอ่านบทความวิกิพีเดียนี้: http://en.wikipedia.org/wiki/Template_method_pattern


3
รูปแบบวิธีการของ @deadalnix Template นั้นค่อนข้างอันตราย คุณสามารถจบลงด้วยรหัสคู่ที่สูงและเริ่มแฮ็คโค้ดเพื่อขยายคลาสนามธรรมที่เทมเพลตเพื่อจัดการ "อีกหนึ่งกรณี"
quant_dev

9
ดูเหมือนว่าจะเป็นรูปแบบต่อต้าน คุณสามารถได้รับสิ่งเดียวกันกับองค์ประกอบกับอินเทอร์เฟซ สิ่งเดียวกันใช้กับคลาสบางส่วนด้วยวิธีนามธรรม แต่แล้วบังคับให้รหัสลูกค้าไปยังระดับชั้นย่อยและแทนที่พวกคุณควรจะมีการดำเนินการได้รับการฉีด ดู: en.wikipedia.org/wiki/Composition_over_inheritance#Benefits
back2dos

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

3
@deadalnix: การบอกว่าการมีเพศสัมพันธ์แบบต่อเนื่องจะลดลงได้ดีที่สุดด้วยรูปแบบเทมเพลตคือการเขียนโปรแกรมลัทธิขนส่งสินค้า (โดยใช้รูปแบบของรัฐ / กลยุทธ์ / โรงงานอาจทำงานได้ดีเช่นกัน) ตามที่สันนิษฐานว่าจะต้องลดลงเสมอ การมีเพศสัมพันธ์ตามลำดับมักเป็นผลมาจากการเปิดเผยการควบคุมที่ละเอียดมากบางสิ่งบางอย่างซึ่งไม่มีความหมายอะไรนอกจากการแลกเปลี่ยน แต่นั่นก็ไม่ได้หมายความว่าฉันไม่สามารถเขียนเสื้อคลุมที่ไม่มีการเชื่อมต่อแบบต่อเนื่องโดยใช้องค์ประกอบ ความจริงแล้วมันทำให้ง่ายขึ้นมาก
back2dos

4
Java ตอนนี้มีการใช้งานเริ่มต้นสำหรับอินเตอร์เฟส นั่นเปลี่ยนคำตอบไหม?
raptortech97

15

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

public void DoTask()
{
    doSetup();
    DoWork();
    doCleanup();
}

protected abstract void DoWork();

นั่นเป็นวิธีที่ดีพอสมควรในการติดตั้งรูในรูปแบบตรงกลางโดยที่คลาสไม่ได้รับรู้เกี่ยวกับการตั้งค่าและกิจกรรมการล้างข้อมูล หากไม่มีวิธีการที่เป็นนามธรรมคุณจะต้องพึ่งพาชั้นเรียนที่ได้รับการนำไปใช้DoTaskและการจดจำการโทรbase.DoSetup()และbase.DoCleanup()ตลอดเวลา

แก้ไข

นอกจากนี้ขอขอบคุณ deadalnix สำหรับการโพสต์ลิงก์ไปยังรูปแบบวิธีการเทมเพลตซึ่งเป็นสิ่งที่ฉันได้อธิบายไว้ข้างต้นโดยที่ไม่รู้ชื่อจริง :)


2
+1, ฉันชอบคำตอบของคุณถึง deadalnix ' โปรดทราบว่าคุณสามารถใช้วิธีเทมเพลตได้อย่างตรงไปตรงมามากขึ้นโดยใช้ผู้รับมอบสิทธิ์ (ใน C #):public void DoTask(Action doWork)
Joh

1
@Joh - จริง แต่นั่นไม่จำเป็นต้องดีเท่านี้ขึ้นอยู่กับ API ของคุณ ถ้าชั้นฐานของคุณเป็นFruitและชั้นของคุณได้รับคือAppleคุณต้องการที่จะเรียกไม่ได้myApple.Eat() myApple.Eat((a) => howToEatApple(a))นอกจากนี้คุณยังไม่ต้องการที่จะมีการโทรApple base.Eat(() => this.howToEatMe())ฉันคิดว่ามันสะอาดกว่าที่จะแทนที่วิธีนามธรรม
Scott Whitlock

1
@Scott Whitlock: ตัวอย่างของคุณที่ใช้แอปเปิ้ลและผลไม้นั้นค่อนข้างห่างไกลจากความเป็นจริงที่จะตัดสินว่าจะไปเพื่อการสืบทอดนั้นดีกว่าหรือเปล่า เห็นได้ชัดว่าคำตอบคือ "ขึ้นอยู่กับ" ดังนั้นจึงเหลือพื้นที่สำหรับการโต้วาที ... อย่างไรก็ตามฉันพบว่าวิธีการเทมเพลตนั้นเกิดขึ้นมากมายระหว่างการรีแฟคเตอร์เช่นเมื่อลบรหัสที่ซ้ำกัน ในกรณีเช่นนี้ฉันมักไม่ต้องการยุ่งกับลำดับชั้นของประเภทและฉันชอบที่จะอยู่ห่างจากมรดก การผ่าตัดแบบนี้จะทำกับลูกแกะได้ง่ายกว่า
Joh

คำถามนี้แสดงให้เห็นมากขึ้นกว่าโปรแกรมที่เรียบง่ายของรูปแบบวิธีการแม่ - รัฐ / ด้านที่ไม่ใช่แบบสาธารณะเป็นที่รู้จักกันใน C ++ ชุมชนเป็นรูปแบบการเชื่อมต่อขององค์กรไม่แสวงหาเสมือน โดยการมีฟังก์ชั่นที่ไม่ใช่เสมือนสาธารณะห่อเวอร์ชวลเสมือน - แม้ว่าในขั้นต้นจะไม่ทำอะไรเลยนอกจากเรียกหลัง - คุณยังคงมีจุดของการปรับแต่งสำหรับการติดตั้ง / ล้างข้อมูลการบันทึกการทำโปรไฟล์การตรวจสอบความปลอดภัยเป็นต้น
Tony

10

ไม่พวกเขาไม่ล้าสมัย

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

ถ้าชุดของคลาสที่ต้องใช้อย่างใดอย่างหนึ่งเหล่านี้มีพฤติกรรมทั่วไปที่พวกเขาใช้ร่วมกัน (คลาสที่เกี่ยวข้องฉันหมายถึง), จากนั้นไปสำหรับคลาส / วิธีนามธรรม

ตัวอย่าง: เสมียน, เจ้าหน้าที่, ผู้อำนวยการ - คลาสเหล่านี้ทั้งหมดมี CalculateSalary () เหมือนกัน, ใช้คลาสฐานที่เป็นนามธรรม CalculateSalary () สามารถนำไปใช้ต่างกันได้ แต่มีบางสิ่งอื่น ๆ เช่น GetAttendance () ตัวอย่างเช่น

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

ตัวอย่าง: วัวม้านั่งรถยนต์ telesope ที่ไม่เกี่ยวข้องกับคลาส แต่สามารถเรียงลำดับได้ในอาร์เรย์

ความแตกต่างนี้มักจะถูกละเว้นเมื่อเข้าหาจากมุมมอง polymorphic แต่โดยส่วนตัวฉันรู้สึกว่ามีสถานการณ์ที่คนฉลาดกว่าคนอื่นด้วยเหตุผลที่อธิบายไว้ข้างต้น


6

นอกเหนือจากคำตอบที่ดีอื่น ๆ แล้วยังมีความแตกต่างพื้นฐานระหว่างอินเตอร์เฟสและคลาสนามธรรมที่ไม่มีใครพูดถึงโดยเฉพาะนั่นคืออินเตอร์เฟสนั้นมีความน่าเชื่อถือน้อยกว่ามากดังนั้นจึงกำหนดภาระการทดสอบที่สูงกว่าคลาสนามธรรม ตัวอย่างเช่นลองพิจารณารหัส C # นี้:

public abstract class Frobber
{
    private Frobber() {}
    public abstract void Frob(Frotz frotz);
    private class GreenFrobber : Frobber
    { ... }
    private class RedFrobber : Frobber
    { ... }
    public static Frobber GetFrobber(bool b) { ... } // return a green or red frobber
}

public sealed class Frotz
{
    public void Frobbit(Frobber frobber)
    {
         ...
         frobber.Frob(this);
         ...
    }
}

ฉันรับประกันว่าจะมีเพียงสองเส้นทางรหัสฉันต้องทดสอบ ผู้เขียน Frobbit สามารถพึ่งพาข้อเท็จจริงที่ว่ากบเป็นสีแดงหรือสีเขียว

ถ้าเราพูดว่า:

public interface IFrobber
{
    void Frob(Frotz frotz);
}
public class GreenFrobber : IFrobber
{ ... }
public class RedFrobber : Frobber
{ ... }

public sealed class Frotz
{
    public void Frobbit(IFrobber frobber)
    {
         ...
         frobber.Frob(this);
         ...
    }
}

ตอนนี้ฉันไม่รู้อะไรเลยเกี่ยวกับผลกระทบของการเรียก Frob ที่นั่น ฉันต้องแน่ใจว่ารหัสทั้งหมดใน Frobbit นั้นแข็งแกร่งต่อการใช้ IFrobber ที่เป็นไปได้แม้แต่การดำเนินการโดยผู้ที่ไร้ความสามารถ (ไม่ดี) หรือเป็นศัตรูกับฉันหรือผู้ใช้ของฉัน (แย่ยิ่งกว่า)

คลาสนามธรรมช่วยให้คุณหลีกเลี่ยงปัญหาเหล่านี้ได้ ใช้มัน!


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

1
ประการแรกผมไม่เคยบอกว่ามันเป็นเรื่องที่ดีหรือคุณธรรม คุณใส่มันเข้าไปในปากของฉัน ประการที่สอง (เป็นจุดที่แท้จริงของฉัน): มันไม่มีอะไรนอกจากข้อแก้ตัวที่แย่สำหรับคุณสมบัติภาษาที่ขาดหายไป สุดท้ายมีวิธีแก้ปัญหาโดยไม่ต้องเรียนนามธรรม: pastebin.com/DxEh8Qfz ในทางตรงกันข้ามวิธีการของคุณใช้คลาสที่ซ้อนกันและเป็นนามธรรมการขว้างทั้งหมดยกเว้นรหัสที่ต้องการความปลอดภัยร่วมกันเป็นโคลนก้อนใหญ่ ไม่มีเหตุผลที่ดีที่ RedFrobber หรือ GreenFrobber ควรเชื่อมโยงกับข้อ จำกัด ที่คุณต้องการบังคับใช้ มันเพิ่มการมีเพศสัมพันธ์และล็อคในการตัดสินใจจำนวนมากโดยไม่มีประโยชน์ใด ๆ
back2dos

1
การบอกว่าวิธีการแบบนามธรรมนั้นล้าสมัยนั้นไม่ผิดโดยไม่ต้องสงสัยเลย แต่การอ้างในทางกลับกันว่าพวกเขาควรได้รับความนิยมมากกว่าส่วนต่อประสานกำลังเข้าใจผิด พวกเขาเป็นเพียงเครื่องมือสำหรับการแก้ปัญหาที่แตกต่างจากส่วนต่อประสาน
Groo

2
"มีความแตกต่างพื้นฐาน [... ] อินเทอร์เฟซมีความน่าเชื่อถือน้อยกว่า [... ] มากกว่าคลาสที่เป็นนามธรรม" ฉันไม่เห็นด้วยความแตกต่างที่คุณแสดงในรหัสของคุณขึ้นอยู่กับข้อ จำกัด การเข้าถึงซึ่งฉันคิดว่าไม่มีเหตุผลใดที่จะแตกต่างอย่างมีนัยสำคัญระหว่างอินเทอร์เฟซและคลาสนามธรรม มันอาจเป็นเช่นนั้นใน C # แต่คำถามคือผู้ไม่เชื่อเรื่องภาษา
Joh

1
@ back2dos: ฉันแค่อยากจะชี้ให้เห็นว่าวิธีการแก้ปัญหาของ Eric ในความเป็นจริงใช้ประเภทข้อมูลพีชคณิต: คลาสนามธรรมเป็นประเภทผลรวม การเรียกใช้เมธอด abstract เหมือนกับการจับคู่รูปแบบเหนือชุดของตัวแปร
Rodrick Chapman

4

คุณพูดมันเอง:

คุณต้องการคลาสนามธรรมที่มีการใช้งานบางอย่างหรือไม่ สร้างอินเตอร์เฟสสร้างคลาส รับชั้นเรียนใช้อินเตอร์เฟซ

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


ไม่ต้องพูดถึงว่าหากคลาสไม่ได้รับส่วนต่อประสาน (ซึ่งไม่ได้กล่าวถึงควร) คุณต้องเขียนฟังก์ชั่นการส่งต่อในบางภาษา
Sjoerd

อืม "งานจำนวนมาก" เพิ่มเติมที่คุณกล่าวถึงก็คือคุณได้สร้างอินเทอร์เฟซและให้ชั้นเรียนใช้มัน - มันดูเหมือนว่าจะทำงานมากหรือไม่? ยิ่งไปกว่านั้นอินเทอร์เฟซช่วยให้คุณสามารถใช้อินเทอร์เฟซจากลำดับชั้นใหม่ซึ่งจะไม่ทำงานกับคลาสฐานนามธรรม
Bill K

4

ในขณะที่ฉันแสดงความคิดเห็นในโพสต์ @deadnix: การใช้งานบางส่วนเป็นรูปแบบการต่อต้านแม้ว่าความจริงที่ว่ารูปแบบแม่แบบทำให้พวกเขาเป็นทางการ

วิธีแก้ปัญหาแบบสะอาดสำหรับวิกิพีเดียตัวอย่างของรูปแบบเทมเพลต :

interface Game {
    void initialize(int playersCount);
    void makePlay(int player);
    boolean done();
    void finished();
    void printWinner();
}
class GameRunner {
    public void playOneGame(int playersCount, Game game) {
        game.initialize(playersCount);
        int j = 0;
        for (int i = 0; !game.finished(); i++)
             game.makePlay(i % playersCount);
        game.printWinner();
    }
} 
class Monopoly implements Game {
     //... implementation
}

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


+1 ในฐานะที่เป็นหมายเหตุด้าน: "การใช้งานบางส่วนเป็นรูปแบบการต่อต้านแม้ว่าความจริงที่ว่ารูปแบบแม่แบบทำให้พวกเขาเป็นทางการ" คำอธิบายเกี่ยวกับวิกิพีเดียกำหนดรูปแบบได้อย่างหมดจดเฉพาะตัวอย่างรหัสคือ "ผิด" (ในแง่ที่ว่ามันใช้การสืบทอดเมื่อไม่ต้องการใช้และมีทางเลือกที่ง่ายกว่าอยู่แล้วดังที่แสดงไว้ด้านบน) กล่าวอีกนัยหนึ่งฉันไม่คิดว่ารูปแบบตัวเองคือการตำหนิเฉพาะวิธีที่ผู้คนมักจะใช้มัน
Joh

2

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


-1 ฉันไม่เข้าใจว่า "รหัสทั่วไปกับการสืบทอด" เกี่ยวข้องกับคำถามนี้อย่างไร คุณควรอธิบายหรือแสดงเหตุผลว่าทำไม "คลาสนามธรรมมีข้อได้เปรียบที่สำคัญกว่าอินเทอร์เฟซ"
Joh

1

คลาสนามธรรมไม่ใช่อินเตอร์เฟส เป็นคลาสที่ไม่สามารถยกตัวอย่างได้

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

แต่คุณจะมีคลาสที่ไร้ประโยชน์ จำเป็นต้องใช้วิธีการที่เป็นนามธรรมในการกรอกข้อมูลลงในช่องการทำงานในชั้นฐาน

ตัวอย่างเช่นกำหนดคลาสนี้

public abstract class Frobber {
    public abstract void Frob();

    public abstract boolean IsFrobbingNeeded { get; }

    public void FrobUntilFinished() {
        while (IsFrobbingNeeded) {
            Frob();
        }
    }
}

คุณจะใช้ฟังก์ชั่นพื้นฐานนี้อย่างไรในคลาสที่ไม่มีFrob()หรือIsFrobbingNeeded?


1
ไม่สามารถสร้างอินเทอร์เฟซได้
Sjoerd

@Sererd: แต่คุณต้องมีคลาสพื้นฐานที่มีการใช้งานร่วมกัน ที่ไม่สามารถเป็นส่วนต่อประสานได้
กำหนดค่า

1

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


0

ฉันไม่คิดว่าพวกเขาล้าสมัยโดยอินเทอร์เฟซ แต่พวกเขาอาจล้าสมัยโดยรูปแบบกลยุทธ์

การใช้หลักของคลาสนามธรรมคือการเลื่อนส่วนหนึ่งของการใช้งาน จะพูดว่า "การใช้งานส่วนนี้ของชั้นเรียนสามารถทำให้แตกต่าง"

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


0

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

ที่กล่าวว่าถ้าเราใช้การเปรียบเทียบในโลกแห่งความเป็นจริงมีการใช้งานเท่าไรสำหรับอินเทอร์เฟซที่บริสุทธิ์ปราศจากการทำงานและสถานะอย่างสมบูรณ์ ถ้าฉันใช้ USB เป็นตัวอย่างนั่นเป็นอินเทอร์เฟซที่เสถียรพอสมควร (ฉันคิดว่าตอนนี้เราอยู่ที่ USB 3.2 แต่มันก็ยังรักษาความเข้ากันได้ย้อนหลังได้)

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

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

และ ณ จุดนั้นเราอาจมีผู้ผลิตบางรายที่แนะนำปัญหาที่แตกต่างจากผู้อื่น หากเราจำเป็นต้องอัปเดตข้อมูลจำเพาะเราอาจมีการใช้งานพอร์ต USB คอนกรีตที่แตกต่างกัน 200 แบบพร้อมวิธีการแก้ไขปัญหาข้อมูลจำเพาะที่ต้องอัปเดตและทดสอบ ผู้ผลิตบางรายอาจพัฒนาการใช้งานมาตรฐานโดยพฤตินัยที่พวกเขาใช้ร่วมกัน (คลาสพื้นฐานแบบอะนาล็อกของคุณที่ใช้อินเทอร์เฟซนั้น) แต่ไม่ใช่ทั้งหมด บางรุ่นอาจช้ากว่ารุ่นอื่น ๆ บางคนอาจมีปริมาณงานที่ดีขึ้น แต่แฝงเร้นหรือแย่ลง บางคนอาจใช้พลังงานแบตเตอรี่มากกว่าคนอื่น บางตัวอาจหลุดลอกออกมาและไม่ทำงานกับฮาร์ดแวร์ทั้งหมดที่ควรจะทำงานกับพอร์ต USB บางคนอาจต้องติดตั้งเครื่องปฏิกรณ์นิวเคลียร์เพื่อใช้งานซึ่งมีแนวโน้มที่จะทำให้ผู้ใช้งานได้รับพิษจากรังสี

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

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

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