以监听zookeeper watcher监听事件处理逻辑为例,可以看出process监听方法中,不同事件触发处理逻辑中有很多if-elseif结构
public class ZkDemo implements Watcher {
private static final String connectString = "localhost:2181";
private static Stat stat = new Stat();
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
private static String path = "/node1";
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zooKeeper = new ZooKeeper(connectString, 5000, new ZkDemo());
countDownLatch.await();
// 创建节点
String ret = zooKeeper.create(path, "11".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// true继续监听
zooKeeper.getData(ret, true, stat);
// 修改节点
Stat stat1 = zooKeeper.setData(ret, "222".getBytes(), 0);
Stat stat2 = zooKeeper.setData(ret, "222".getBytes(), 1);
// 删除节点
zooKeeper.delete(path, 2);
}
@Override
public void process(WatchedEvent watchedEvent) {
// 监听连接状态,开放闭锁
if (watchedEvent.getState().equals(Event.KeeperState.SyncConnected)) {
countDownLatch.countDown();
if (watchedEvent.getType().equals(Event.EventType.None) && null == watchedEvent.getPath()) {
System.out.println("watcher监听事件的状态:" + watchedEvent.getState() + "-->watcher监听事件的类型:" + watchedEvent.getType());
} else if (watchedEvent.getType().equals(Event.EventType.NodeDataChanged)) {
try {
System.out.println("节点数据修改:" + watchedEvent.getPath() + "修改后的数据为" + zooKeeper.getData(watchedEvent.getPath(), true, stat) );
} catch (KeeperException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else if (watchedEvent.getType().equals(Event.EventType.NodeDeleted)) {
System.out.println("节点被删除:" + watchedEvent.getPath());
}
}
}
}
优化思路,使用策略模式+工厂模式
策略模式:定义解决事件的接口EventStrategy,接口方法为handle(...),参数是所有事件处理时需要调用什么参数就传什么参数,可以看到上面的用到了
watchedEvent, zooKeeper, stat三个参数,所以事件策略类接口应该定义如下:
public interface EventStrategy {
/**
* 事件监听处理策略
*/
void handle(WatchedEvent watchedEvent, ZooKeeper zooKeeper, Stat stat) throws Exception;
}
策略实现类,也就是针对每个事件的处理策略,直接针对每种if条件的处理逻辑复制到hadle方法即可
None事件策略类(连接后没有事件发生时)
public class NoneEventStrategy implements EventStrategy {
@Override
public void handle(WatchedEvent watchedEvent, ZooKeeper zooKeeper, Stat stat) throws Exception {
System.out.println("watcher监听事件的状态:" + watchedEvent.getState() + "-->watcher监听事件的类型:" + watchedEvent.getType());
}
}
Modify事件策略类(节点数据修改时)
public class ModifyEventStrategy implements EventStrategy {
@Override
public void handle(WatchedEvent watchedEvent, ZooKeeper zooKeeper, Stat stat) throws Exception {
System.out.println("节点数据修改:" + watchedEvent.getPath() + "修改后的数据为:" + zooKeeper.getData(watchedEvent.getPath(), true, stat) );
}
}
Delete事件策略类(节点删除时)
public class DeleteEventStrategy implements EventStrategy {
@Override
public void handle(WatchedEvent watchedEvent, ZooKeeper zooKeeper, Stat stat) throws Exception {
System.out.println("节点被删除:" + watchedEvent.getPath());
}
}
工厂模式:根据不同的事件获取相应的事件策略
工厂类需要根据WatchedEvent.getType()来匹配具体的事件策略处理类。首先工厂类肯定需要先将所有的事件策略类对象放到工厂内部,这里使用Map实现。
public class EventStrategyFactory {
public static final Map<Watcher.Event.EventType, EventStrategy> map = new HashMap<>();
// 初始化工厂
static {
map.put(Watcher.Event.EventType.None, new NoneEventStrategy());
map.put(Watcher.Event.EventType.NodeDataChanged, new ModifyEventStrategy());
map.put(Watcher.Event.EventType.NodeDeleted, new DeleteEventStrategy());
}
// 从工厂类中的map中获取具体的事件策略
public static EventStrategy getEventStrategy(WatchedEvent event) {
return map.get(event.getType());
}
}
使用策略模式+工厂模式后的版本,感觉清爽多了
核心是根据工厂类获取对应的事件策略类,事件策略类又由接口统一定义,不同实现类实现不同的处理策略(handle方法)
public class ZkDemo implements Watcher {
private static final String connectString = "61.144.207.233:2191";
private static Stat stat = new Stat();
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private static ZooKeeper zooKeeper;
private static String path = "/node1";
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
zooKeeper = new ZooKeeper(connectString, 5000, new ZkDemo());
countDownLatch.await();
// 创建节点
String ret = zooKeeper.create(path, "11".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
// true继续监听
zooKeeper.getData(ret, true, stat);
// 修改节点
Stat stat1 = zooKeeper.setData(ret, "222".getBytes(), 0);
Stat stat2 = zooKeeper.setData(ret, "222".getBytes(), 1);
// 删除节点
zooKeeper.delete(path, 2);
}
@Override
public void process(WatchedEvent watchedEvent) {
// 监听连接状态,开放闭锁
if (watchedEvent.getState().equals(Event.KeeperState.SyncConnected)) {
try {
countDownLatch.countDown();
EventStrategy eventStrategy = EventStrategyFactory.getEventStrategy(watchedEvent);
eventStrategy.handle(watchedEvent, zooKeeper, stat);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}