package org.rui.pattern; import junit.framework.*; /** * 为了使同一个方法调用可以产生不同的行为,State 模式在代理(surrogate)的 * 生命周期内切换它所对应的实现(implementation)。当你发现,在决定如何实现任 对象去耦(Object decoupling) * http://blog.csdn.net/lxwde 28 何一个方法之前都必须作很多测试的情况下,这是一种优化实现代码的方法。例如, * 童话故事青蛙王子就包含一个对象(一个生物),这个对象的行为取决于它自己所处 的状态。你可以用一个布尔(boolean)值来表示它的状态,测试程序如下: * * @author Administrator * */ class Creature { private boolean isFrog = true; public void greet() { if (isFrog) System.out.println("Ribbet!"); else System.out.println("Darling!"); } public void kiss() { isFrog = false; } } public class KissingPrincess extends TestCase { Creature creature = new Creature(); public void test() { creature.greet(); creature.kiss(); creature.greet(); } public static void main(String args[]) { junit.textui.TestRunner.run(KissingPrincess.class); } } // /:~
package org.rui.pattern; import junit.framework.*; /** * 状态模式:改变对象的行为 一个用来改变类的(状态的)对象。 迹象:几乎所有方法里都出现(相同的)条件(表达式)代码。 * * * 但是,greet() 方法(以及其它所有在完成操作之前必须测试 isFrog 值的那些方 * 法)最终要产生一大堆难以处理的代码。 * 如果把这些操作都委托给一个可以改变的状 态对象(State object),那代码会简单很多。 * * @author Administrator * */ class Creature2 { private interface State { String response(); } private class Frog implements State { public String response() { return "Ribbet!"; } } private class Prince implements State { public String response() { return "Darling!"; } } private State state = new Frog(); public void greet() { System.out.println(state.response()); } public void kiss() { // 改变对象状态 state = new Prince(); } } public class KissingPrincess2 extends TestCase { Creature2 creature = new Creature2(); public void test() { creature.greet(); creature.kiss(); creature.greet(); } public static void main(String args[]) { junit.textui.TestRunner.run(KissingPrincess2.class); } } // /:~
package org.rui.pattern; import org.junit.Test; import junit.framework.*; /** * 下面的代码演示了 State 模式的基本结构 */ interface State { void operation1(); void operation2(); void operation3(); } class ServiceProvider { private State state; public ServiceProvider(State state) { this.state = state; } public void changeState(State newState) { state = newState; System.out.println("========changeState===========" + newState.getClass().getSimpleName()); } // 通过方法调用实现 public void service1() { // ... state.operation1(); // ... state.operation3(); } public void service2() { // ... state.operation1(); // ... state.operation2(); } public void service3() { // ... state.operation3(); // ... state.operation2(); } } class Implementation1 implements State { public void operation1() { System.out.println("Implementation1.operation1()"); } public void operation2() { System.out.println("Implementation1.operation2()"); } public void operation3() { System.out.println("Implementation1.operation3()"); } } class Implementation2 implements State { public void operation1() { System.out.println("Implementation2.operation1()"); } public void operation2() { System.out.println("Implementation2.operation2()"); } public void operation3() { System.out.println("Implementation2.operation3()"); } } public class StateDemo extends TestCase { static void run(ServiceProvider sp) { sp.service1(); sp.service2(); sp.service3(); } ServiceProvider sp = new ServiceProvider(new Implementation1()); @Test public void test() { run(sp); sp.changeState(new Implementation2()); run(sp); } /* * public static void main(String args[]) { * junit.textui.TestRunner.run(StateDemo.class); } */ } // /:~ /* * 在 main( )函数里,先用到的是第一个实现,然后转入第二个实现。 当你自己实现 State 模式的时候就会碰到很多细节的问题,你必须根据自己的需 * 要选择合适的实现方法,比如用到的状态(State)是否要暴露给调用的客户,以及如 何使状态发生变化。有些情况下(比如 Swing 的 * LayoutManager),,客户端可以直接 传对象进来,但是在 KissingPrincess2.java 那个例子里,状态对于客户端来说是不 * 可见的。此外,用于改变状态的机制可能很简单也可能很复杂-比如本书后面将要提 到的状态机(State * Machine),那里会讲到一系列的状态以及改变状态的不同机制。 上面提到 Swing 的 LayoutManager 那个例子非常有趣,它同时体现了 * Strategy 模 式和 State 模式的行为。 Proxy 模式和 State 模式的区别在于它们所解决的问题不同。《设计模式》里是这 么描述 * Proxy 模式的一般应用的: 1. 远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代理。 RMI 编译器(rmic)在创建 * stubs 和 skeletons 的时候会自动为你创建一 个远端代理。 2. 虚代理(Virtual proxy),根据需要,在创建复杂对象时使用 * “延迟初 始化(lazy initialization)” . 3. 保护代理(protection proxy) 用于你不希望客户端程序员完全控制被代 * 理对象(proxied object)的情况下。 4. 智能引用(smart reference). 当访问被代理对象时提供额外的动作。 * 例如,它可以用来对特定对象的引用进行计数,从而实现写时复制 (copy-on-write),进而避免对象别名(object aliasing). 更简单的 * 一个例子是用来记录一个特定方法被调用的次数。 你可以把 java 里的引用(reference)看作是一种保护代理,它控制对分配在堆 * (heap)上的实际对象的访问(而且可以保证你不会用到一个空引用(null reference))。 『重写:在《设计模式》一书里,Proxy 模式和 * State 模式被认为是互不相干的, 因为那本书给出的用以实现这两种模式的结构是完全不同的(我认为这种实现有点武 断)。尤其是 State * 模式,它用了一个分离的实现层次结构,但我觉着完全没有必 要,除非你认定实现代码不是由你来控制的(当然这也是一种可能的情况,但是如果 * 代码是由你来控制的,那还是用一个单独的基类更简洁实用)。此外,Proxy 模式的实 * 现不需要用一个公共的基类,因为代理对象只是控制对被代理对象的访问。尽管有细 节上的差异,Proxy 模式和 State * 模式都是用一个代理(surrogate)把方法调用传递 给实现对象。』 */
时间: 2024-10-10 22:30:09