Jak*_*ake 25 java design-patterns listeners
通常我会遇到一个给定对象需要有很多监听器的情况.例如,我可能有
class Elephant {
public void addListener( ElephantListener listener ) { ... }
}
Run Code Online (Sandbox Code Playgroud)
但我会遇到很多这样的情况.也就是说,我也会有一个Tiger
对象TigerListener
.现在,TigerListener
s和ElephantListener
s完全不同:
interface TigerListener {
void listenForGrowl( Growl qrowl );
void listenForMeow( Meow meow );
}
Run Code Online (Sandbox Code Playgroud)
而
interface ElephantListener {
void listenForStomp( String location, double intensity );
}
Run Code Online (Sandbox Code Playgroud)
我发现我总是必须在每个动物类中继续重新实现广播机制,并且实现总是相同的.有首选模式吗?
mat*_*t b 28
Listener
您可以发送它,而不是每个事件类型都有特定的方法,更改接口以接受泛型Event
类.然后Event
,如果需要,可以将子类化为特定的子类型,或者使其包含诸如的状态double intensity
.
然后TigerListener和ElephentListener成为
interface TigerListener {
void listen(Event event);
}
Run Code Online (Sandbox Code Playgroud)
实际上,您可以进一步将此接口重构为简单Listener
:
interface Listener {
void listen(Event event);
}
Run Code Online (Sandbox Code Playgroud)
Listener
然后,您的实现可以包含他们关心的特定事件所需的逻辑
class TigerListener implements Listener {
@Overrides
void listen(Event event) {
if (event instanceof GrowlEvent) {
//handle growl...
}
else if (event instance of MeowEvent) {
//handle meow
}
//we don't care about any other types of Events
}
}
class ElephentListener {
@Overrides
void listen(Event event) {
if (event instanceof StompEvent) {
StompEvent stomp = (StompEvent) event;
if ("north".equals(stomp.getLocation()) && stomp.getDistance() > 10) {
...
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
订阅者和发布者之间的关键关系是发布者可以向订阅者发送事件,不一定是它可以向其发送某些类型的事件 - 这种类型的重构将该逻辑从接口推送到特定的实现中.
Sur*_*gch 13
对于那些来这里只想做一个听众的人来说,这是一个更普遍的答案.我总结了从CodePath 创建自定义侦听器.如果您需要更多解释,请阅读该文章.
这是步骤.
这是在需要与某个未知父级进行通信的子类中.
public class MyClass {
// interface
public interface MyClassListener {
// add whatever methods you need here
public void onSomeEvent(String title);
}
}
Run Code Online (Sandbox Code Playgroud)
将私有侦听器成员变量和公共setter方法添加到子类.
public class MyClass {
// add a private listener variable
private MyClassListener mListener = null;
// provide a way for another class to set the listener
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
// interface from Step 1
public interface MyClassListener {
public void onSomeEvent(String title);
}
}
Run Code Online (Sandbox Code Playgroud)
子对象现在可以在侦听器接口上调用方法.一定要检查null,因为可能没有人在听.(也就是说,父类可能没有为我们的侦听器调用setter方法.)
public class MyClass {
public void someMethod() {
// ...
// use the listener in your code to fire some event
if (mListener != null)
mListener.onSomeEvent("hello");
}
// items from Steps 1 and 2
private MyClassListener mListener = null;
public void setMyClassListener(MyClassListener listener) {
this.mListener = listener;
}
public interface MyClassListener {
public void onSomeEvent(String myString);
}
}
Run Code Online (Sandbox Code Playgroud)
父级现在可以使用我们在子类中设置的侦听器.
public class MyParentClass {
private void someMethod() {
MyClass object = new MyClass();
object.setMyClassListener(new MyClass.MyClassListener() {
@Override
public void onSomeEvent(String myString) {
// handle event
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
public class MyParentClass implements MyClass.MyClassListener {
public MyParentClass() {
MyClass object = new MyClass();
object.setMyClassListener(this);
}
@Override
public void onSomeEvent(String myString) {
// handle event
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
34556 次 |
最近记录: |