代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
远程代理服务:Java使用RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象创建和服务对象相同的方法。C#则采用Romting
场景:承接状态模式中的糖果贩卖机,通过代理模式及Remoting实现远程监控机器的剩余糖果数量,机器位置和机器状态。
//代理GumballMachine的类
//代理模式,为限制GumballMachine的访问,将其包装为GumballMachineProxy代理
//继承MarshalByRefObject类,才可以通过Remoting进行序列化传输。
public class GumballMachineProxy : MarshalByRefObject
{
GumballMachine gumballMachine;
public GumballMachineProxy(GumballMachine gumballMachine)
{
this.gumballMachine = gumballMachine;
}
//获取糖果数量
public int getCount()
{
return gumballMachine.getCount();
}
//获取机器位置
public string getLocation()
{
return gumballMachine.getLocation();
}
//获取机器状态
public 状态模式.State getState()
{
return gumballMachine.getState();
}
}
//监控机器的类
public class GumballMonitor
{
GumballMachineProxy gumballMachine;
public GumballMonitor(GumballMachineProxy gumballMachine)
{
this.gumballMachine = gumballMachine;
}
public void report()
{
Console.WriteLine("----GumballMachine Report----");
Console.WriteLine("Current inventory:{0} gumballs", gumballMachine.getCount());
Console.WriteLine("Gumball Machine:{0}",gumballMachine.getLocation());
Console.WriteLine("Cuttent state:{0}", gumballMachine.getState().GetType().Name);
Console.WriteLine("------------ End ------------\n");
}
}
//需要修改的类
//因为需要传输状态类,所以状态基类改成抽象类并继承MarshalByRefObject
public abstract class State : MarshalByRefObject
{
//投入硬币
public abstract void insertQuarter();
//退出硬币
public abstract void ejectQuarter();
//拨动曲柄
public abstract void turnCrank();
//施行
public abstract void dispense();
}
//服务端:糖果贩卖机
static void Main(string[] args)
{
GumballMachine gumballMachine = new GumballMachine(ConfigurationManager.AppSettings.Get("MachineLocation"), 100);
GumballMachineProxy machineProxy = new GumballMachineProxy(gumballMachine);
int port = Convert.ToInt32(ConfigurationManager.AppSettings.Get("GumballMachineTcpChannelPort"));
//定义访问接口
TcpChannel tcpServerChannel = new TcpChannel(port);
ChannelServices.RegisterChannel(tcpServerChannel, false);
//将machineProxy作为服务辅助对象
RemotingServices.Marshal(machineProxy, "GumballMachineProxy", typeof(GumballMachineProxy));
while (gumballMachine.getCount() >= 0)
{
Console.WriteLine("操作提示:1.投币,2.摇杆,3.退币");
string num = Console.ReadLine();
if (num.Equals("1"))
{
gumballMachine.insertQuarter();
}
else if (num.Equals("2"))
{
gumballMachine.turnCrank();
}
else if (num.Equals("3"))
{
gumballMachine.ejectQuarter();
}
}
}
//客户端:监控控制台
static void Main(string[] args)
{
TcpChannel tcpServerChannel = new TcpChannel(0);
ChannelServices.RegisterChannel(tcpServerChannel, false);
List<GumballMachineProxy> remoteobjs = new List<GumballMachineProxy>();
remoteobjs.Add((GumballMachineProxy)Activator.GetObject(typeof(GumballMachineProxy), "tcp://192.168.1.43:8080/GumballMachineProxy"));
remoteobjs.Add((GumballMachineProxy)Activator.GetObject(typeof(GumballMachineProxy), "tcp://192.168.1.42:8080/GumballMachineProxy"));
while (true)
{
Console.WriteLine("查看GumballMachine报告,请按回车键:");
Console.ReadLine();
Console.Clear();
for (int i = 0; i < remoteobjs.Count; i++)
{
GumballMonitor gumballMotnitor = new GumballMonitor(remoteobjs[i]);
try
{
Console.WriteLine("编号({0})GumballMachine", i);
gumballMotnitor.report();
}
catch (RemotingException e)
{
Console.WriteLine("编号({0})GumballMachine:RemotingException;原因:{1};位置:{2}", i, e.Message, e.StackTrace);
}
catch (System.Net.Sockets.SocketException e)
{
Console.WriteLine("编号({0})GumballMachine:SocketException;原因:{1};位置:{2}", i, e.Message, e.StackTrace);
}
}
}
}
//测试环境:将糖果贩卖机部署到局域网IP分别为42,43的机器上并运行,然后运行监控控制台程序
//测试结果:
1.对42的糖果贩卖进行投币操作
2.查看监视控制台
3.摇取糖果
4.再次查看监控报告