package gumballrmi; import java.rmi.Remote; import java.rmi.RemoteException; /** * 让GumballMachine准备好当一个远程服务 * @author wwj * 代理模式的使用例子 */ public interface GumballMachineRemote extends Remote { public int getCount() throws RemoteException; public String getLocation() throws RemoteException; public State getState() throws RemoteException; }
package gumballrmi; import java.io.*; /** * 2013/7/13 * @author wwj * 扩展Serializable接口,则State的所有子类就可以在网络上传送了 */ public interface State extends Serializable { public void insertQuarter(); public void ejectQuarter(); public void turnCrank(); public void dispense(); }
package gumballrmi; public class NoQuarterState implements State { //对于State的每个实现,我们都在GumballMachine实例变量前面加上transient关键字,这就就告诉JVM不要序列化这个字段 transient GumballMachine gumballMachine; public NoQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("You inserted a quarter"); gumballMachine.setState(gumballMachine.getHasQuarterState()); } public void ejectQuarter() { System.out.println("You haven't inserted a quarter"); } public void turnCrank() { System.out.println("You turned, but there's no quarter"); } public void dispense() { System.out.println("You need to pay first"); } public String toString() { return "waiting for quarter"; } }
package gumballrmi; import java.util.Random; public class HasQuarterState implements State { Random randomWinner = new Random(System.currentTimeMillis()); //随机数产生器 transient GumballMachine gumballMachine; public HasQuarterState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("You can't insert another quarter"); } public void ejectQuarter() { System.out.println("Quarter returned"); gumballMachine.setState(gumballMachine.getNoQuarterState()); } public void turnCrank() { System.out.println("You turned..."); int winner = randomWinner.nextInt(10); //参数0~10的随机数 if((winner == 0) && (gumballMachine.getCount() > 1)) { //如果随机树为0,且足够的糖果的话,则可以得到两颗糖果 gumballMachine.setState(gumballMachine.getWinnerState()); } else { gumballMachine.setState(gumballMachine.getSoldState()); } } public void dispense() { System.out.println("No gumball dispensed"); } public String toString() { return "waiting for turn of crank"; } }
package gumballrmi; public class SoldOutState implements State { transient GumballMachine gumballMachine; public SoldOutState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("You can't insert a quarter, the machine is sold out"); } public void ejectQuarter() { System.out.println("You can't eject, you haven't inserted a quarter yet"); } public void turnCrank() { System.out.println("You turned, but there are no gumballs"); } public void dispense() { System.out.println("No gumball dispensed"); } public String toString() { return "sold out"; } }
package gumballrmi; public class SoldState implements State { transient GumballMachine gumballMachine; public SoldState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("Please wait, we're already giving you a gumball"); } public void ejectQuarter() { System.out.println("Sorry, you already turned the crank"); } public void turnCrank() { System.out.println("Turning twice doesn't get you another gumball!"); } public void dispense() { gumballMachine.releaseBall(); if (gumballMachine.getCount() > 0) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } else { System.out.println("Oops, out of gumballs!"); gumballMachine.setState(gumballMachine.getSoldOutState()); } } public String toString() { return "dispensing a gumball"; } }
package gumballrmi; public class WinnerState implements State { transient GumballMachine gumballMachine; public WinnerState(GumballMachine gumballMachine) { this.gumballMachine = gumballMachine; } public void insertQuarter() { System.out.println("Please wait, we're already giving you a Gumball"); } public void ejectQuarter() { System.out.println("Please wait, we're already giving you a Gumball"); } public void turnCrank() { System.out.println("Turning again doesn't get you another gumball!"); } public void dispense() { System.out.println("YOU'RE A WINNER! You get two gumballs for your quarter"); gumballMachine.releaseBall(); if (gumballMachine.getCount() == 0) { gumballMachine.setState(gumballMachine.getSoldOutState()); } else { gumballMachine.releaseBall(); if (gumballMachine.getCount() > 0) { gumballMachine.setState(gumballMachine.getNoQuarterState()); } else { System.out.println("Oops, out of gumballs!"); gumballMachine.setState(gumballMachine.getSoldOutState()); } } } public String toString() { return "despensing two gumballs for your quarter, because YOU'RE A WINNER!"; } }
package gumballrmi; import java.rmi.RemoteException; /** * * @author wwj * 糖果监视器,以便取得机器的位置、糖果的库存量以及当前机器的状态 * 并打印一份可爱的报告 * 这是我们的监视器代码,它使用代理和远程糖果机沟通 */ public class GumballMonitor { GumballMachineRemote gumballMachine; public GumballMonitor(GumballMachineRemote gumballMachine) { this.gumballMachine = gumballMachine; } public void report() { try { System.out.println("Gumball Machine: " + gumballMachine.getLocation()); System.out.println("Current inventory: " + gumballMachine.getCount() + " gumballs"); System.out.println("Current State: " + gumballMachine.getState()); } catch (RemoteException e) { e.printStackTrace(); } } }
package gumballrmi; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; /** * 2013/7/13 * @author wwj * 糖果机成为一个远程服务 * 代理模式: */ public class GumballMachine extends UnicastRemoteObject implements GumballMachineRemote{ State soldOutState; //售空状态 State noQuarterState; //没有投入25分钱 State hasQuarterState; //有25分钱了 State soldState; //出售状态 State winnerState; //10%的中奖率 State state = soldOutState; int count = 0; String location; //新增,位置字段 public GumballMachine(String location, int numberGumballs) throws RemoteException{ soldOutState = new SoldOutState(this); noQuarterState = new NoQuarterState(this); hasQuarterState = new HasQuarterState(this); soldState = new SoldState(this); winnerState = new WinnerState(this); this.count = numberGumballs; if(numberGumballs > 0) { state = noQuarterState; } this.location = location; } public String getLocation() { return location; } public void insertQuarter() { state.insertQuarter(); } public void ejectQuarter() { state.ejectQuarter(); } public void turnCrank() { state.turnCrank(); state.dispense(); } void setState(State state) { this.state = state; } public State getState() { return state; } void releaseBall() { System.out.println("A gumball comes rolling out the slot..."); if(count != 0) { count = count - 1; } } public State getSoldOutState() { return soldOutState; } public State getNoQuarterState() { return noQuarterState; } public State getHasQuarterState() { return hasQuarterState; } public State getSoldState() { return soldState; } public State getWinnerState() { return winnerState; } public int getCount() { return count; } public String toString() { StringBuffer result = new StringBuffer(); result.append("\nMighty Gumball, Inc."); result.append("\nJava-enabled Standing Gumball Model #2004"); result.append("\nInventory: " + count + " gumball"); if (count != 1) { result.append("s"); } result.append("\n"); result.append("Machine is " + state + "\n"); return result.toString(); } }
package gumballrmi; import java.rmi.Naming; public class GumballMachineTestDrive { public static void main(String[] args) { GumballMachineRemote gumballMachine = null; int count = 0; if(args.length < 2) { System.out.println("GumballMachine<name> <inventory>"); System.exit(1); } try { count = Integer.parseInt(args[1]); gumballMachine = new GumballMachine(args[0], count); Naming.rebind("//" + args[0] + "/gumballmachine", gumballMachine); } catch (Exception e) { e.printStackTrace(); } } }