diff --git a/docs/book/25-Patterns.md b/docs/book/25-Patterns.md index cb43a04..9bd8e81 100644 --- a/docs/book/25-Patterns.md +++ b/docs/book/25-Patterns.md @@ -221,7 +221,205 @@ Implementation.h() **状态模式** +状态模式向代理对象添加了更多的实现,以及在代理对象的生命周期内从一个实现切换到另一种实现的方法: +```Java +// patterns/StateDemo.java // Simple demonstration of the State pattern +interface StateBase { + void f(); + + void g(); + + void h(); + + void changeImp(StateBase newImp); +} + +class State implements StateBase { + private StateBase implementation; + + State(StateBase imp) { + implementation = imp; + } + + @Override + public void changeImp(StateBase newImp) { + implementation = newImp; + }// Pass method calls to the implementation: @Override public void f() { implementation.f(); } @Override public void g() { implementation.g(); } @Override + + public void h() { + implementation.h(); + } +} + +class Implementation1 implements StateBase { + @Override + public void f() { + System.out.println("Implementation1.f()"); + } + + @Override + public void g() { + System.out.println("Implementation1.g()"); + } + + @Override + public void h() { + System.out.println("Implementation1.h()"); + } + + @Override + public void changeImp(StateBase newImp) { + } +} + +class Implementation2 implements StateBase { + @Override + public void f() { + System.out.println("Implementation2.f()"); + } + + @Override + public void g() { + System.out.println("Implementation2.g()"); + } + + @Override + public void h() { + System.out.println("Implementation2.h()"); + } + + @Override + public void changeImp(StateBase newImp) { + } +} + +public class StateDemo { + static void test(StateBase b) { + b.f(); + b.g(); + b.h(); + } + + public static void main(String[] args) { + StateBase b = new State(new Implementation1()); + test(b); + b.changeImp(new Implementation2()); + test(b); + } +} +/* Output: +Implementation1.f() +Implementation1.g() +Implementation1.h() +Implementation2.f() +Implementation2.g() +Implementation2.h() +*/ +``` + +在main()中,首先使用第一个实现,然后改变成第二个实现。代理模式和状态模式的区别在于它们解决的问题。设计模式中描述的代理模式的常见用途如下: + +1. 远程代理。它在不同的地址空间中代理对象。远程方法调用(RMI)编译器rmic会自动为您创建一个远程代理。 + +2. 虚拟代理。这提供了“懒加载”来根据需要创建“昂贵”的对象。 + +3. 保护代理。当您希望对代理对象有权限访问控制时使用。 + +4. 智能引用。要在被代理的对象被访问时添加其他操作。例如,跟踪特定对象的引用数量,来实现写时复制用法,和防止对象别名。一个更简单的例子是跟踪特定方法的调用数量。您可以将Java引用视为一种保护代理,因为它控制在堆上实例对象的访问(例如,确保不使用空引用)。 + +在设计模式中,代理模式和桥接模式并不是相互关联的,因为它们被赋予(我认为是任意的)不同的结构。桥接模式,特别是使用一个单独的实现,但这似乎对我来说是不必要的,除非你确定该实现是你无法控制的(当然有可能,但是如果您编写所有代码,那么没有理由不从单基类的优雅中受益)。此外,只要代理对象控制对其“前置”对象的访问,代模式理就不需要为其实现使用相同的基类。不管具体情况如何,在代理模式和桥接模式中,代理对象都将方法调用传递给具体实现对象。 + +**状态机** + +桥接模式允许程序员更改实现,状态机利用一个结构来自动地将实现更改到下一个。当前实现表示系统所处的状态,系统在不同状态下的行为不同(因为它使用桥接模式)。基本上,这是一个利用对象的“状态机”。将系统从一种状态移动到另一种状态的代码通常是模板方法模式,如下例所示: + +```Java +// patterns/state/StateMachineDemo.java +// The StateMachine pattern and Template method +// {java patterns.state.StateMachineDemo} +package patterns.state; + +import onjava.Nap; + +interface State { + void run(); +} + +abstract class StateMachine { + protected State currentState; + + Nap(0.5); +System.out.println("Washing"); new + + protected abstract boolean changeState(); + + // Template method: + protected final void runAll() { + while (changeState()) // Customizable + currentState.run(); + } +} + +// A different subclass for each state: +class Wash implements State { + @Override + public void run() { + } +} + +class Spin implements State { + @Override + public void run() { + System.out.println("Spinning"); + new Nap(0.5); + } +} + +class Rinse implements State { + @Override + public void run() { + System.out.println("Rinsing"); + new Nap(0.5); + } +} + +class Washer extends StateMachine { + private int i = 0; + + // The state table: + private State[] states = {new Wash(), new Spin(), new Rinse(), new Spin(),}; + + Washer() { + runAll(); + } + + @Override + public boolean changeState() { + if (i < states.length) { + // Change the state by setting the + // surrogate reference to a new object: + currentState = states[i++]; + return true; + } else return false; + } +} + +public class StateMachineDemo { + public static void main(String[] args) { + new Washer(); + } +} +/* +Output: +Washing +Spinning +Rinsing +Spinning +*/ +``` + +在这里,控制状态的类(本例中是状态机)负责决定下一个状态。然而,状态对象本身也可以决定下一步移动到什么状态,通常基于系统的某种输入。这是更灵活的解决方案。