【问题标题】:Subscription model with generics - implement multiple generic interfaces具有泛型的订阅模型 - 实现多个泛型接口
【发布时间】:2014-03-29 15:11:52
【问题描述】:

所以我尝试使用泛型创建订阅模型。它看起来不错,但现在我遇到了一些问题。

接收者

public interface Receiver<E> {
    public void receive(E event);
}

订阅注册表

public class ClientRegistry<T> {
    private Set<Receiver<T>> clients = new HashSet<Receiver<T>>();

    public void subscribe(Receiver<T> client) {
        clients.add(client);
    }

    public void unsubscribe(Receiver<T> client) {
        clients.remove(client);
    }

    public void broadcast(T eventObject) {
        for(Receiver<T> client: clients) {
            client.receive(eventObject);
        }       
    }   
}

到目前为止听起来不错,嗯?

现在问题来了:

public class Screen implements Receiver<KeyEvent>, Receiver<MouseMoveEvent> {
    @Override
    public void receive(KeyEvent event)
    {
        // work
    }

    @Override
    public void receive(MouseMoveEvent event)
    {
        // work
    }
}

现在这是无效的语法:

The interface Receiver cannot be implemented more than once
with different arguments: Receiver<MouseMoveEvent> and Receiver<KeyEvent>

如何更改我的系统以使其尽可能通用,但使其正常工作?

【问题讨论】:

  • 据我所知,即使没有泛型,你也不能两次实现一个接口。
  • 是的,这就是为什么我认为使用泛型我可以做到。无论如何,如何以更好的方式做到这一点?
  • 为什么不能直接编程到界面? (实现 Receiver)?
  • 但事件不是接口。
  • 其实没关系,只要是KeyEvent和MouseMoveEvent的基类就可以了

标签: java generics design-patterns subscription


【解决方案1】:

不要让 Screen 类本身实现两个 Receiver 接口。相反,使用组合:

public class Screen {
    private Receiver<KeyEvent> keyReceiver = new Receiver<KeyEvent>() {
        ...
    };

    private Receiver<MouseEvent> mouseReceiver = new Receiver<MouseEvent>() {
        ...
    };
}

【讨论】:

    【解决方案2】:

    我会颠倒顺序,并使用Visitor Pattern:

    import java.util.*;
    
    interface Event{
        void receive(Receiver receiver);    
    }
    
    class KeyEvent implements Event{
        @Override
        public void receive(Receiver receiver){
            receiver.receive(this);
        }   
    }
    
    class MouseEvent implements Event {
        @Override
        public void receive(Receiver receiver){
            receiver.receive(this);
        }   
    }
    
    interface Receiver {
        void receive(KeyEvent event);
        void receive(MouseEvent event);
    }
    
    class ClientRegistry {
        private Set<Receiver> clients = new HashSet<Receiver>();
    
        public void subscribe(Receiver client) {
            clients.add(client);
        }
    
        public void unsubscribe(Receiver client) {
            clients.remove(client);
        }
    
        public void broadcast(Event eventObject) {
            for(Receiver client: clients) {
                eventObject.receive(client);
            }       
        }   
    }
    
    public class Screen implements Receiver {
    
        public void receive(KeyEvent event) {
            //work
            System.out.println("Processing key event");
        }
        public void receive(MouseEvent event) {
            //work
            System.out.println("Processing mouse event");
        }
    
    
        public static void main(String[] args){
            ClientRegistry registry = new ClientRegistry();
            registry.subscribe(new Screen());
            registry.broadcast(new MouseEvent());
        }
    }
    

    没有办法生成 Receiver 接口,但它确实是类型安全的,如您所见,我颠倒了顺序,因为现在是事件选择接收器,而不是其他情况。

    【讨论】:

    • 其实我现在用的是类似的模式,所以我给你点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多