1、3. 4. void noResultTest(String str);5. 这个接口有两个方法要实现,就是有返回值的调用resultTest和不需要返回值的调用noResultTest,我们把这个接口用一个代理类来实现,目的是将方法调用转化为对象,这样就可以将多个请求(多个方法调)放到一个容器中缓存起来,然后统一处理,因为Java不支持方法指针,所以把方法调用转换为对象,然后在这个对象上统一执行它们的方法,不仅可以做到异步处理,而且可以将代表方法调用的请求对象序列化后通过网络传递到另一个机器上执行(RMI).这也是Java回调机制最有力的实现.一个简单的例子.如果 1: 做A如果 2: 做B
2、如果 3: 做C如果有1000个情况,你不至于用1000个case吧?以后再增加呢?所以如果C/C+程序员,会这样实现: (c和c+定义结构不同)type define struct MyStructint mark;(*fn) (); MyList;然后你可以声明这个结构数据:1,A,2,B,3,C做一个循环:for(i=0;ilength;i+) if(数据组i.mark = 传入的值)(数据组i.*fn)();break;简单说c/c+中将要被调用的函数可以被保存起来,然后去访问,调用,而Java中,我们无法将一个方法保存,除了直接调用,所以将要调用的方法用子类来实现,然后把这些子类实例
3、保存起来,然后在这些子类的实现上调用方法:interface Imyvoid test();class A implements Imypublic void test()System.out.println(A):class B implements ImyBclass C implements ImyCclass MyStruct Imy m;public MyStruct(int mark,Imy m)this.mark = amrk;this.m = m数组: new MyStruct(1,new A(),new MyStruct(2,new B(),new MyStruct(3,ne
4、w C()for(int i=0;数组.length;i+) if(参数 =数组i.mark) 数组i.m.test();这样把要调用的方法转换为对象的保程不仅仅是可以对要调用的方法进行调度,而且可以把对象序列化后在另一台机器上执行,这样就把调用边界从线程扩展到了机器.回到我们的例子:代理其实就是在接口和实现类之间做一个中间人,一个实现如果直接执行接口的方法,我们无法对这些方法的调用进行控制和跟踪等行为。代理模式的意义在于用户要访问一个实现时其实是先访问这个对象的代理,由这个代理来决定如何使用实现类,这样可以起到控制,延迟加载,缓存,隔离被代理的真正实现,也可以对真正的实现的并发性,安全性和其
5、它附加操作进行控制。对于用户而言,请求时并不知道他请求的是代理对象,而是直接请求接口的操作,所以代理要和实现类一样来实现类一样“继承”同一接口,在接口的方法中不去真正的实现而是调用实现类的实现。1. class Proxy implements ISmartAxmanService 2. private final Scheduler scheduler; / 这个调度者就是代理用来控制实现类的调用的 3. private final SmartAxmanServiceImp serviceImp; / 这个实现类完成接口方法的真正实现 4. 5. public Proxy(Scheduler
6、 scheduler, SmartAxmanServiceImp serviceImp) 6. this.scheduler = scheduler;7. this.serviceImp = serviceImp;8. 9. 10. public Result resultTest(int count, char c) 11. 12. FutureResult futrue = new FutureResult();13. / 如果弱化代理的调度控制,这里就应该象下面注释掉的代码:14. / doBeforeImpResultTest();15. / serviceImp.ResultTest
7、();16. / doAfterImpResultTest();17. / 这里进行了更复杂的控制,所以把实现和调度传递给ResultRequest来执行。18. this.scheduler.invoke(new ResultRequest(serviceImp, futrue, count, c);19. return futrue;20. 21. 22. public void noResultTest(String str) 23. 24. / 同上 25. this.scheduler.invoke(new NoResultRequest(this.serviceImp, str);
8、26. 27. SmartAxmanServiceImp就是去真实地实现方法:1. class SmartAxmanServiceImp implements ISmartAxmanService 2. public Result resultTest(int count, char c) 3. char buf = new charcount;4. for (int i = 0; i = this.requestQueue.length) 16. try 17. this.wait();18. catch (Throwable t) 20. this.requestQueuethis.tai
9、l = request;21. tail = (tail + 1) % this.requestQueue.length; /如果到数组最后则从头开始 22. count+;23. this.notifyAll();24. 25. 26. public synchronized MethodRequest takeRequest() 27. while (this.count = 0) 28. try 29. this.wait();30. catch (Throwable t) 31. 32. 33. MethodRequest request = this.requestQueuethis
10、.head;34. 35. / this.requestQueuethis.head = null;36. / 考虑注释掉的这一行代码,对于循环的队列还不是非常明显,如果是非循环的队列。这个元素 37. / 可能永远被持有,比如一个Stack中如果put了,再pop时,虽然对象被取走了,栈顶指针指象了index+1;38. / 但底层的数组中那个index位置的对象还被数组本身引用着,如果没有put动作替换这个位置的句柄指向一个 39. / 新的对象,则已经pop出去的对象一直被数组本身引用着。所以对于处于数据结构中的对象如果要从中取出, 40. / 数据结果本身要取消对它的引用。41. 42
11、. this.head = (this.head + 1) % this.requestQueue.length;43. count-;44. this.notifyAll();45. return request;46. 47. 为了将方法调用转化为对象,我们通过实现MethodRequest对象的execute方法来方法具体方法转换成具体对象:1. public abstract class MethodRequest 3. protected final SmartAxmanServiceImp serviceImp;4. protected final FutureResult fut
12、ure;5. 6. protected MethodRequest(SmartAxmanServiceImp serviceImp, FutureResult future) 8. this.future = future;10. 11. public abstract void execute();13. 14. 15. public class ResultRequest extends MethodRequest 16. private final int count;17. private final char c;18. 19. public ResultRequest(SmartA
13、xmanServiceImp serviceImp, 20. FutureResult future, 21. int count, 22. char c) 23. super(serviceImp, future);24. this.count = count;25. this.c = c;27. 28. public void execute() 29. Result result = serviceImp.resultTest(this.count, this.c);30. this.future.setResult(result);33. 34. public class NoResu
14、ltRequest extends MethodRequest 35. private String str;36. 37. public NoResultRequest(SmartAxmanServiceImp serviceImp, String str) 38. super(serviceImp, null);39. this.str = str;40. 42. public void execute() 43. this.serviceImp.noResultTest(str);44. 45. 而返回的数据我们也将真实数据的获取和取货凭证逻辑分离,这里虽然是经典的Future模式,但我
15、们可以看到,FutureResult其本质也是Result与RealResult的代理,或桥梁。1. public abstract class Result 2. public abstract Object getResultValue();3. 5. public class FutureResult extends Result 6. 7. private Result result;8. private boolean completed;10. public synchronized void setResult(Result result) 11. this.result = r
16、esult;12. pleted = true;13. this.notifyAll();14. 15. 16. public synchronized Object getResultValue() 17. while (!pleted) 18. try 19. this.wait();20. catch (Throwable t) 21. 22. return this.result.getResultValue();23. 26. public class RealResult extends Result 28. private final Object resultValue;29.
17、 30. public RealResult(Object resultValue) 31. this.resultValue = resultValue;34. public Object getResultValue() 35. return this.resultValue;36. 37. OK,现在这个异步消息处理器已经有了模型,这个异步处理器中有哪些对象参与呢?SmartAxmanServiceImp 忠心做真实的事务SmartQueue将请求缓存起来以便调度Scheduler对容器中的请求根据一定原则进行调度执行Proxy将特定方法请求转换为特定对象所有这些都是这个异步处理器的核心
18、部件,既然是核心部件,我们就要进行封装而不能随便让调用者来修改,所以我们用工厂模式(我KAO,我实在不想提模式但有时找不到其它词来表述)来产生处理器ISmartAxmanService对象:1. class SmartAxmanServiceFactory 2. public static synchronized ISmartAxmanService createService() 3. SmartAxmanServiceImp imp = new SmartAxmanServiceImp();4. SmartQueue queue = new SmartQueue();5. Schedul
19、er st = new Scheduler(queue);6. Proxy p = new Proxy(st, imp);7. st.start();8. return p;好了,我们现在用两个请求的产生者不停产生请求:ResultInvokeThread 发送有返回值的请求:1. public class ResultInvokeThread extends Thread 2. private final ISmartAxmanService service;3. private final char c;5. public ResultInvokeThread(String name, ISmartAxmanService service) 6. this.service = service;7. this.c = name.charAt(0);10. public void run() 11. try 12. int i = 0;13. while (true) 14. Result result = this.service.resultTest(i+, c);15. Thread.sleep(10);16. String value = (String) result.getResultValue()
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1