ความแตกต่างระหว่างพร็อกซีและรูปแบบมัณฑนากร


136

คุณสามารถให้คำอธิบายที่ดีใด ๆ สิ่งที่เป็นความแตกต่างระหว่างพร็อกซีและมัณฑนากร ?

ความแตกต่างหลัก ๆ ที่ฉันเห็นคือเมื่อเราสมมติว่าProxyใช้องค์ประกอบและDecoratorใช้การรวมแล้วดูเหมือนว่าจะชัดเจนว่าโดยการใช้Decoratorsหลาย (หนึ่งหรือมากกว่า) คุณสามารถปรับเปลี่ยน / เพิ่มฟังก์ชันการทำงานเพื่ออินสแตนซ์ที่มีอยู่ก่อนพร็อกซีมีอินสแตนซ์ภายในของคลาสพร็อกซีและผู้รับมอบสิทธิ์เพิ่มคุณสมบัติเพิ่มเติม (ลักษณะการทำงานของพร็อกซี)

คำถามคือ - พร็อกซีที่สร้างด้วยการรวมยังเป็นพร็อกซีหรือมากกว่ามัณฑนากรหรือไม่ อนุญาต (ตามคำจำกัดความในรูปแบบ GoF) เพื่อสร้างพร็อกซีที่มีการรวมหรือไม่



5
คุณได้รับแนวคิดว่า Proxy ใช้องค์ประกอบและมัณฑนากรใช้การรวมที่ไหน
CPerkins

1
@ CPerkins เห็นความคิดเห็นของฉันสำหรับคำตอบ Rahul Tripathi
Łukasz Rzeszotarski

1
และมัณฑนากร ( patterns.cs.up.ac.za/examples/ch2/decorator-theory.cs ) - การรวมอย่างชัดเจนพร็อกซี ( patterns.cs.up.ac.za/examples/ch2/proxy-theory.cs ) - องค์ประกอบที่เห็นได้ชัด
hyankov

คำตอบ:


17

นี่คือคำพูดโดยตรงจาก GoF (หน้า 216)

แม้ว่ามัณฑนากรสามารถมีการใช้งานที่คล้ายกันเป็นผู้รับมอบฉันทะ แต่นักตกแต่งมีวัตถุประสงค์ที่แตกต่างกัน มัณฑนากรเพิ่มความรับผิดชอบอย่างน้อยหนึ่งอย่างให้กับวัตถุในขณะที่พร็อกซีควบคุมการเข้าถึงวัตถุ

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

คำตอบที่ได้รับความนิยมระบุว่าพร็อกซีรู้ประเภทของตัวแทนที่เป็นรูปธรรม จากคำพูดนี้เราจะเห็นว่าไม่เป็นความจริงเสมอไป

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

เราอาจพูดได้ว่า Proxy เป็นกล่องดำในขณะที่ Decorator เป็นกล่องสีขาว

ความสัมพันธ์ขององค์ประกอบระหว่าง wrapper และผู้รับมอบสิทธิ์เป็นความสัมพันธ์ที่ไม่ถูกต้องที่จะมุ่งเน้นเมื่อเทียบกับพร็อกซีกับมัณฑนากรเนื่องจากองค์ประกอบเป็นคุณลักษณะที่ทั้งสองรูปแบบมีเหมือนกัน ความสัมพันธ์ระหว่าง wrapper และไคลเอนต์คือความแตกต่างของทั้งสองรูปแบบ

  • มัณฑนากรแจ้งและให้อำนาจลูกค้า
  • พร็อกซี จำกัด และเลิกใช้ไคลเอ็นต์ของตน

113

ความแตกต่างที่แท้จริงไม่ใช่ความเป็นเจ้าของ (องค์ประกอบกับการรวม) แต่เป็นข้อมูลประเภท

มัณฑนากรจะเสมอผ่านผู้รับมอบสิทธิ์ของตน พร็อกซี่ อาจจะสร้างมันขึ้นมาเองหรือเขาอาจจะมีมันฉีด

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

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

คำตอบสำหรับคำถามของคุณคือ "ใช่"


2
"แต่พร็อกซีรู้อยู่เสมอว่าผู้รับมอบสิทธิ์ประเภทใด (มากกว่า)" ฉันไม่คิดว่ามันจะเป็นเรื่องจริง ลองจินตนาการถึง Remote proxy กลไกการมอบฉันทะไม่จำเป็นต้องทราบข้อมูลเฉพาะของวัตถุระยะไกล ระบบรีโมตลงทะเบียนอ็อบเจ็กต์ด้วยอินเตอร์เฟสที่ระบุ และโลคัลพร็อกซีจะเปิดเผยอินเตอร์เฟสเดียวกัน
Alexey

3
ฉันเข้าเรียนวิชานี้ที่อเมซอนจากอาจารย์ที่มาเยี่ยมที่รู้จักสิ่งของของเขา มีความแตกต่างระหว่างการใช้งาน "พร็อกซี" ที่ปฏิบัติการได้ (เช่นกับเว็บเซอร์วิส) และรูปแบบการออกแบบพร็อกซี UMLs ของรูปแบบพรอกซีและรูปแบบของมัณฑนากรอาจแตกต่างกัน แต่ไม่มีสิ่งใดป้องกันไม่ให้พร็อกซีมี API เดียวกับผู้รับมอบสิทธิ์ มัณฑนากรเป็นเซตย่อยของพร็อกซีที่เข้มงวด แต่มัณฑนากรอาจยังคงเรียกว่าพร็อกซีขึ้นอยู่กับว่า API ที่รับประกันจะเหมือนกันหรือไม่
cdunn2001

85

รูปแบบมัณฑนากรมุ่งเน้นไปที่การเพิ่มฟังก์ชั่นไปยังวัตถุในขณะที่รูปแบบพร็อกซีมุ่งเน้นไปที่การควบคุมการเข้าถึงวัตถุ

แก้ไข: -

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


5
พร็อกซียังสามารถใช้เพื่อเพิ่มฟังก์ชันการทำงานได้ คิดถึงผู้รับมอบฉันทะ AOP
Sotirios Delimanolis

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

ในกรณีนี้เมื่ออินสแตนซ์ 'ซ่อนอยู่' ในพร็อกซีความแตกต่างชัดเจนสำหรับฉัน (ตามที่ฉันเขียน) แต่ฉันคิดว่าบ่อยครั้งที่คนเรียกว่าคลาสพร็อกซีซึ่งใช้วัตถุพร็อกซีซึ่งถูกส่งเป็นพารามิเตอร์คอนสตรัคเตอร์ ในกรณีนี้ความแตกต่างของการเพิ่มฟังก์ชั่นหรือการควบคุมใหม่นั้นบางมากสำหรับฉัน
Łukasz Rzeszotarski

5
ความสัมพันธ์ระหว่างพร็อกซีและเรื่องจริงโดยทั่วไปแล้วจะถูกกำหนดในเวลารวบรวมพร็อกซีทำให้อินสแตนซ์ของมันเป็นบางอย่างในขณะที่มัณฑนากรหรืออะแดปเตอร์ถูกกำหนดให้กับเรื่องที่รันไทม์ หวังว่าจะทำให้รู้สึก !!! :)
Rahul Tripathi

1
คุณสามารถเพิ่มบรรทัดนี้ในคำตอบของคุณได้หรือไม่
Łukasz Rzeszotarski

49

มัณฑนากรรับการอ้างอิงสำหรับวัตถุตกแต่ง (มักจะผ่านตัวสร้าง) ในขณะที่ผู้รับมอบอำนาจรับผิดชอบในการทำเช่นนั้นด้วยตนเอง

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

พร็อกซีมักจะใช้กรอบเพื่อเพิ่มความปลอดภัยหรือแคช / ขี้เกียจและสร้างโดยกรอบ (ไม่ใช่นักพัฒนาปกติเอง)

มัณฑนากรมักจะใช้ในการเพิ่มพฤติกรรมใหม่ในการเรียนเก่าหรือมรดกโดยนักพัฒนาตัวเองขึ้นอยู่กับอินเตอร์เฟซที่ระดับค่อนข้างจริงแล้ว (ดังนั้นจึงทำงานในช่วงกว้างของอินสแตนซ์อินเตอร์เฟซ, พร็อกซี่ที่อยู่รอบ ๆ ชั้นคอนกรีต)


22

ความแตกต่างที่สำคัญ:

  1. Proxyจัดเตรียมอินเตอร์เฟสเดียวกัน มัณฑนากรมอบส่วนต่อประสานที่ได้รับการปรับปรุง
  2. มัณฑนากรและพร็อกซี่มีวัตถุประสงค์ที่แตกต่างกัน แต่โครงสร้างที่คล้ายกัน ทั้งสองอธิบายถึงวิธีการให้ระดับของการอ้อมไปยังวัตถุอื่นและการใช้งานเก็บการอ้างอิงถึงวัตถุที่พวกเขาส่งต่อการร้องขอ
  3. มัณฑนากรสามารถดูได้ว่าเป็นคอมโพสิตที่เสื่อมสภาพด้วยองค์ประกอบเดียวเท่านั้น อย่างไรก็ตามมัณฑนากรเพิ่มความรับผิดชอบเพิ่มเติม - มันไม่ได้มีไว้สำหรับการรวมวัตถุ
  4. มัณฑนากรสนับสนุนองค์ประกอบซ้ำ
  5. มัณฑนากรระดับประกาศองค์ประกอบความสัมพันธ์กับจอแอลซีดีอินเตอร์เฟซ (ต่ำสุดคลาสหาร) และสมาชิกข้อมูลนี้จะเริ่มต้นได้ในตัวสร้างตน
  6. ใช้พร็อกซีสำหรับการเริ่มต้นที่ขี้เกียจการปรับปรุงประสิทธิภาพโดยการแคชวัตถุและควบคุมการเข้าถึงลูกค้า / ผู้โทร

บทความการทำซอร์สโค้ดอ้างอิงความคล้ายคลึงและความแตกต่างอย่างยอดเยี่ยม

คำถาม / ลิงก์ SE ที่เกี่ยวข้อง:

เมื่อใดที่จะใช้รูปแบบมัณฑนากร?

อะไรคือความแตกต่างที่แน่นอนระหว่างรูปแบบของอะแดปเตอร์และพร็อกซี?


3

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

ในขณะที่รูปแบบทั้งสองมีความคล้ายคลึงกันในโครงสร้างส่วนใหญ่ของความซับซ้อนของพร็อกซีอยู่ในการรับรองการสื่อสารที่เหมาะสมกับวัตถุต้นฉบับ ในทางกลับกันมัณฑนากรมุ่งเน้นไปที่การใช้งานพฤติกรรมที่เพิ่มเข้ามา


คุณกำลังพูดอะไรที่แตกต่างจากคำตอบ 4 ข้อที่มีอยู่แล้วที่นี่
Stephen Rauch

ฉันไม่รู้ว่ามันมีทั้งหมดหรือไม่ ฉันแค่รู้สึกอยากที่จะพูดสอดหลังจากอ่านคำตอบก่อนหน้า
James Lin

1

เอาในขณะที่จะคิดออกนี้คำตอบและสิ่งที่มันจริงๆหมายถึง ตัวอย่างบางส่วนควรทำให้ชัดเจนยิ่งขึ้น

Proxy ครั้งแรก:

public interface Authorization {
    String getToken();
} 

และ:

// goes to the DB and gets a token for example
public class DBAuthorization implements Authorization {
    @Override
    public String getToken() {
        return "DB-Token";
    }
}

และมีผู้โทรมาคนนี้Authorizationเป็นคนที่น่ารัก

class Caller {
    void authenticatedUserAction(Authorization authorization) {
        System.out.println("doing some action with : " + authorization.getToken());
    }
}

ไม่มีอะไรผิดปกติจนถึงตอนนี้ใช่ไหม? รับโทเค็นจากบริการบางอย่างใช้โทเค็นนั้น ตอนนี้มีความต้องการเพิ่มเติมในรูปภาพเพิ่มการบันทึก: หมายถึงบันทึกโทเค็นทุกครั้ง มันง่ายสำหรับกรณีนี้เพียงแค่สร้างProxy:

public class LoggingDBAuthorization implements Authorization {

    private final DBAuthorization dbAuthorization = new DBAuthorization();

    @Override
    public String getToken() {
        String token = dbAuthorization.getToken();
        System.out.println("Got token : " + token);
        return token;
    }
}

เราจะใช้มันอย่างไร

public static void main(String[] args) {
    LoggingDBAuthorization loggingDBAuthorization = new LoggingDBAuthorization();

    Caller caller = new Caller();
    caller.authenticatedUserAction(loggingDBAuthorization);
}

ขอให้สังเกตว่าLoggingDBAuthorization ถือDBAuthorizationตัวอย่างของ ทั้งสองLoggingDBAuthorizationและการดำเนินการDBAuthorization Authorization

  • พร็อกซีจะระงับการนำไปปฏิบัติบางส่วน ( DBAuthorization) ของอินเตอร์เฟสพื้นฐาน ( Authorization) กล่าวอีกนัยหนึ่งพร็อกซีรู้ว่าสิ่งใดที่ถูกพร็อกซี

Decorator:

มันเริ่มต้นสวยมากเหมือนกับProxyอินเทอร์เฟซ:

public interface JobSeeker {
    int interviewScore();
}

และการดำเนินการของมัน:

class Newbie implements JobSeeker  {
    @Override
    public int interviewScore() {
        return 10;
    }
}

และตอนนี้เราต้องการเพิ่มผู้สมัครที่มีประสบการณ์มากขึ้นนั่นคือคะแนนการสัมภาษณ์บวกกับคะแนนจากคนอื่นJobSeeker:

@RequiredArgsConstructor 
public class TwoYearsInTheIndustry implements JobSeeker {

    private final JobSeeker jobSeeker;

    @Override
    public int interviewScore() {
        return jobSeeker.interviewScore() + 20;
    } 
}

แจ้งให้ทราบว่าผมบอกว่าบวกหนึ่งจากผู้หางานอื่น , ไม่ NewbieA Decoratorไม่ทราบว่ามันคืออะไรตกแต่งมันรู้เพียงสัญญาของอินสแตนซ์ที่ตกแต่ง (มันรู้JobSeeker) สังเกตที่นี่ว่าไม่เหมือนProxy; ในทางตรงกันข้ามรู้ว่ามันคืออะไรตกแต่ง

คุณอาจถามว่าจริง ๆ แล้วมีความแตกต่างระหว่างสองรูปแบบการออกแบบในกรณีนี้หรือไม่? เกิดอะไรขึ้นถ้าเราพยายามที่จะเขียนDecoratorเป็นProxy?

public class TwoYearsInTheIndustry implements JobSeeker {

    private final Newbie newbie = new Newbie();

    @Override
    public int interviewScore() {
        return newbie.interviewScore() + 20;
    }
}

นี่เป็นตัวเลือกและเน้นว่ารูปแบบเหล่านี้อยู่ใกล้แค่ไหน พวกเขายังคงมีไว้สำหรับสถานการณ์ที่แตกต่างกันตามที่อธิบายไว้ในคำตอบอื่น ๆ


1

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

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