"สวัสดี อามีโก้"
“สวัสดีครับคุณริชชี่”
"วันนี้ฉันจะอธิบายหัวข้อใหม่และน่าสนใจให้คุณฟัง: พร็อกซีแบบไดนามิก" .
"Java มีหลายวิธีในการเปลี่ยนฟังก์ชันการทำงานของคลาสเฉพาะ..."
"วิธีแรกคือการสืบทอด"
"วิธีที่ง่ายที่สุดในการเปลี่ยนแปลงพฤติกรรมของคลาสคือการสร้างคลาสใหม่ที่สืบทอดคลาสดั้งเดิม (ฐาน) และแทนที่เมธอดของคลาสนั้น จากนั้น แทนที่จะใช้คลาสดั้งเดิม คุณใช้คลาสที่ได้รับมา ตัวอย่างเช่น:"
Reader reader = new UserCustomReader();
"วิธีที่สองคือการใช้คลาส wrapper"
" BufferedReaderเป็นตัวอย่างของคลาสประเภทนี้ ประการแรก มันสืบทอดReaderกล่าวอีกนัยหนึ่ง มันสามารถใช้แทน Reader ได้ อย่างที่สอง มันเปลี่ยนเส้นทางการเรียกทั้งหมดไปยังออบ เจกต์ Reader ดั้งเดิม ซึ่งต้องส่งผ่านไปยังตัวสร้างของออบเจ็กต์ BufferedReader . ตัวอย่างเช่น:"
Reader readerOriginal = new UserCustomReader();
Reader reader = new BufferedReader(readerOriginal);
"วิธีที่สามคือการสร้างพร็อกซีแบบไดนามิก (Proxy)"
"มีคลาสพิเศษใน Java (java.lang.reflect.Proxy) ที่ให้คุณสร้างออบเจกต์ระหว่างการทำงานของโปรแกรม (ไดนามิก) โดยไม่ต้องสร้างคลาสแยกต่างหากสำหรับคลาสนั้น"
"นี่เป็นเรื่องง่ายมากที่จะทำ:"
Reader reader = (Reader)Proxy.newProxyInstance();
"นั่นเป็นสิ่งใหม่สำหรับฉันแล้ว!"
"แต่แน่นอน เราไม่ต้องการออบเจ็กต์ที่ไม่มีเมธอด เราต้องการให้อ็อบเจกต์มีเมธอด และเราต้องการให้ออบเจ็กต์ทำในสิ่งที่เราต้องการ Java ใช้อินเทอร์เฟซพิเศษสำหรับ InvocationHandler ซึ่งสามารถสกัดกั้นการเรียกใช้เมธอดทั้งหมด เชื่อมโยงกับวัตถุพร็อกซี วัตถุพร็อกซีสามารถสร้างได้โดยใช้อินเทอร์เฟซเท่านั้น"
" เรียกใช้ – เป็นชื่อมาตรฐานสำหรับเมธอดหรือคลาสที่มีหน้าที่หลักในการเรียกใช้เมธอดบางอย่าง"
" Handler – เป็นชื่อมาตรฐานสำหรับคลาสที่จัดการเหตุการณ์บางอย่าง ตัวอย่างเช่น คลาสที่จัดการการคลิกเมาส์จะเรียกว่า MouseClickHandler เป็นต้น"
"อินเทอร์เฟซ InvocationHandler มีวิธีการเรียกใช้วิธีเดียว ซึ่งเรียกการเรียกทั้งหมดไปยังวัตถุพร็อกซีตัวอย่างเช่น:"
Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler());
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("yes!");
return null;
}
}
"เมื่อเรียกใช้ เมธอด reader .close () เมธอด invokeจะถูกเรียกใช้ และหน้าจอจะแสดง 'yes!' "
"ดังนั้นเราจึงประกาศCustomInvocationHandlerคลาส และนำ อินเทอร์เฟซ InvocationHandlerและ เมธอดการ เรียกใช้มาใช้ เมื่อเรียกใช้เมธอด จะแสดง 'ใช่!' จากนั้นเราสร้าง ออบเจกต์ CustomInvocationHandlerและส่งต่อไปยัง เมธอด newProxyInstanceเมื่อสร้าง วัตถุพร็อกซี"
"ใช่ ถูกต้องทั้งหมด"
"นี่เป็นเครื่องมือที่ทรงพลังมาก โดยปกติแล้ว พร็อกซีเหล่านี้ถูกสร้างขึ้นเพื่อจำลองวัตถุในโปรแกรมที่กำลังทำงานอยู่บนคอมพิวเตอร์เครื่องอื่น หรือเพื่อควบคุมการเข้าถึง"
"คุณสามารถตรวจสอบสิทธิ์ของผู้ใช้ปัจจุบัน จัดการกับข้อผิดพลาด บันทึกข้อผิดพลาด และอื่นๆ อีกมากมายได้ด้วยวิธีการนี้"
"นี่คือตัวอย่างที่เมธอดเรียกใช้ยังเรียกเมธอดของออปเจกต์ดั้งเดิมด้วย:"
Reader original = new UserCustomReader();
Reader reader = (Reader)Proxy.newProxyInstance(new CustomInvocationHandler(original));
reader.close();
class CustomInvocationHandler implements InvocationHandler
{
private Reader readerOriginal;
CustomInvocationHandler(Reader readerOriginal)
{
this.readerOriginal = readerOriginal;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
if (method.getName().equals("close"))
{
System.out.println("Reader closed!");
}
// This calls the readerOriginal object's close method.
// The method's name and a description of its parameters are stored in the method variable.
return method.invoke(readerOriginal, args);
}
}
"ตัวอย่างนี้มีคุณสมบัติพิเศษสองประการ"
"อย่างแรก ออบเจ็กต์ «ต้นฉบับ» Readerจะถูกส่งผ่านไปยังคอนสตรัคเตอร์ และการอ้างอิงไปยังอ็อบเจ็กต์นั้นจะถูกบันทึกไว้ในCustomInvocationHandler "
"อย่างที่สอง เราเรียกเมธอดเดิมนี้อีกครั้งใน invoke method แต่ครั้งนี้เรียกออปเจ็กต์ «ดั้งเดิม»"
"อ่า พูดอีกอย่างคือ บรรทัดสุดท้ายนี้เรียกเมธอดเดียวกัน แต่ใช้ออปเจ็กต์เดิม:"
return method.invoke(readerOriginal, args);
"ใช่."
"ฉันจะไม่บอกว่ามันชัดเจนมาก แต่ก็ยังเข้าใจได้ หรือดูเหมือนว่า"
"เยี่ยมมาก แล้วอีกอย่าง ในเมธอด newProxyInstance คุณต้องส่งข้อมูลการดูแลเพิ่มเติมอีกเล็กน้อยเพื่อสร้างวัตถุพร็อกซี แต่เนื่องจากเราไม่ได้สร้างวัตถุพร็อกซีขนาดมหึมา ข้อมูลนี้จึงได้รับอย่างง่ายดายจากคลาสเดิม "
"นี่เป็นอีกตัวอย่างหนึ่ง:"
Reader original = new UserCustomReader();
ClassLoader classLoader = original.getClass().getClassLoader();
Class<?>[] interfaces = original.getClass().getInterfaces();
CustomInvocationHandler invocationHandler = new CustomInvocationHandler(original);
Reader reader = (Reader)Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
class CustomInvocationHandler implements InvocationHandler
{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
return null;
}
}
"อ่า ClassLoader และรายการอินเทอร์เฟซ นี่เป็นบางอย่างจาก Reflection ใช่ไหม"
"ใช่."
"ฉันเข้าใจแล้ว ฉันคิดว่าฉันสามารถสร้างวัตถุพร็อกซีแบบดั้งเดิมที่เรียบง่ายสุด ๆ ได้ ถ้าฉันต้องการ"
"จากนั้นไปตรวจสอบกับดิเอโก"
GO TO FULL VERSION