निम्नलिखित @OldCurmudgeon के उत्तर के समान है।
कुंजीपटल listeners
फ़ील्ड भी है। लेकिन मैं इसे इस प्रकार घोषित करता हूं:
private final Map<Class<?>, DelegatingPacketListener> listeners
यहां बिंदु यह है कि हम मानचित्र मूल्य प्रकार के रूप में सूची से छुटकारा पा सकते हैं।
public class WrappingPacketListener<T extends Packet> implements PacketListener<Packet> {
private final Class<T> packetClass;
private final PacketListener<T> wrapped;
public WrappingPacketListener(Class<T> packetClass, PacketListener<T> delegate) {
super();
this.packetClass = packetClass;
this.wrapped = delegate;
}
@Override
public void onOutgoingPacket(Streamer streamer, Packet packet) {
if(packetClass.isInstance(packet)) {
T genericPacket = packetClass.cast(packet);
wrapped.onOutgoingPacket(streamer, genericPacket);
}
}
@Override
public void onIncomingPacket(Streamer streamer, Packet packet) {
if(packetClass.isInstance(packet)) {
T genericPacket = packetClass.cast(packet);
wrapped.onIncomingPacket(streamer, genericPacket);
}
}
}
कृपया ध्यान दें कि प्रकार पैरामीटर T
में उपयोग नहीं किया जाता है:
public class DelegatingPacketListener implements PacketListener<Packet> {
private final List<PacketListener<Packet>> packetListeners;
public DelegatingPacketListener(List<? extends PacketListener<Packet>> packetListeners) {
super();
this.packetListeners = new ArrayList<PacketListener<Packet>>(packetListeners);
}
@Override
public void onOutgoingPacket(Streamer streamer, Packet packet) {
for(PacketListener<Packet> packetListener : packetListeners) {
packetListener.onOutgoingPacket(streamer, packet);
}
}
@Override
public void onIncomingPacket(Streamer streamer, Packet packet) {
for(PacketListener<Packet> packetListener : packetListeners) {
packetListener.onIncomingPacket(streamer, packet);
}
}
public List<PacketListener<Packet>> getPacketListeners() {
return Collections.unmodifiableList(packetListeners);
}
}
अब जब कि DelegatingPacketListener
ही प्रकार Packet
के श्रोताओं हम PacketListener
में से एक अधिक विशिष्ट कार्यान्वयन की जरूरत का समर्थन करता है: DelegatingPacketListener
इस प्रकार घोषित किया जाता है उपकरण लागू करता है। यह केवल कार्यान्वयन के लिए उपयोग किया जाता है। हम प्रत्येक PacketListener
को WrappingPacketListener
में एपीआई में पास कर देंगे। तो कार्यान्वयन इस तरह है:
public List<PacketListener<Packet>> getPacketListeners(Class<?> clazz) {
return Collections.<PacketListener<Packet>>singletonList(listeners.get(clazz));
}
public <T extends Packet> void addPacketListener(Class<T> clazz, PacketListener<T> listener) {
if (listeners.containsKey(clazz) == false) {
listeners.put(clazz, new DelegatingPacketListener(Collections.singletonList(new WrappingPacketListener<T>(clazz, listener))));
return;
}
DelegatingPacketListener existing = listeners.get(clazz);
List<PacketListener<Packet>> newListeners = new ArrayList<PacketListener<Packet>>(existing.getPacketListeners());
newListeners.add(new WrappingPacketListener<T>(clazz, listener));
listeners.put(clazz, new DelegatingPacketListener(newListeners));
}
private <T extends Packet> void notifyListeners(T packet) {
List<PacketListener<Packet>> listeners = streamer.getPacketListeners(packet.getClass());
if (listeners != null) {
for (PacketListener<Packet> packetListener : listeners) {
packetListener.onIncomingPacket(streamer, packet);
}
}
}
एपीआई थोड़ा getPacketListeners
जो अब एक सामान्य प्रकार का उपयोग नहीं करता है के लिए बदल गया है।
OldCurmudgeon के समाधान की तुलना में, यह पहले से मौजूद PacketListener
इंटरफ़ेस के साथ चिपक जाता है और इसे अनचेक कास्ट लागू करने की आवश्यकता नहीं होती है।
ध्यान दें कि कार्यान्वयन मानचित्र कुंजी पर addPacketListener
जरूरतों तुल्यकालन के अंतर्गत प्रयोग की वजह से सुरक्षित थ्रेड नहीं है, (के रूप में प्रश्न में मूल कोड भी जरूरत है)। हालांकि अपरिवर्तनीय DelegatingPacketListener
में पैकेट श्रोताओं की सूची को समाहित करना शायद समवर्ती उद्देश्यों के लिए बेहतर अनुकूल है।
पीईसीएस सिद्धांत का पालन करने का प्रयास करें। यह आपकी चीजों को आसान बना देगा। http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs – Pranalee
कृपया यह न करें कि आप 'ConcurrentMap' का उपयोग करते हैं, फिर भी' addPacketListener' में कोड थ्रेड सुरक्षित नहीं है और मानचित्र पर सिंक्रनाइज़ेशन की आवश्यकता होगी कुंजी। – SpaceTrucker
@ स्पेसट्रकर वास्तव में क्यों है? – Antoniossss