代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代理控制访问的方式:
1.远程代理控制访问远程对象。
2.虚拟代理控制访问创建开销大的资源。
3.保护代理基于权限控制对资源的访问。
代码实现:
1.远程代理控制访问远程对象。
(1)采用java的RMI机制创建一个远程服务,以及一个state接口
import java.rmi.*;
public interface GumballMachineRemote extends Remote{
public int getCount() throws RemoteException;
public String getLocation() throws RemoteException;
public State getState() throws RemoteException;
}
//针对remote服务中的State,创建一个state接口。
import java.io.Serializable;
public interface State extends Serializable{
public void insertQuarter();
public void ejectQuarter();
public void turnCrank();
public void dispense();
}
(2)继承state接口,实现相应的状态
public class HasQuarterState implements State{
//transient 告诉jvm不要序列化这个对象
transient GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) {
// TODO Auto-generated constructor stub
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("You can't insert another quarter.");
}
@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("Quarter returned.");
gumballMachine.setstate(gumballMachine.noquarterstate);
}
@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned.");
gumballMachine.setstate(gumballMachine.soldstate);
}
@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("No gumball dispensed.");
}
}
public class NoQuarterState implements State{
transient GumballMachine gumballmachine;
public NoQuarterState(GumballMachine gumballmachine){
this.gumballmachine = gumballmachine;
}
@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("You inserted a quarter.");
gumballmachine.setstate(gumballmachine.hasquarterstate);
}
@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("You hasn't inserted a quarter.");
}
@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("You turned, but there is no quarter.");
}
@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("You need to pay first.");
}
}
public class SoldOutState implements State{
transient GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
// TODO Auto-generated constructor stub
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("Sorry, gumball has sold out.");
}
@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("eject quarter.");
}
@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("Sorry , you need to pay first.");
}
@Override
public void dispense() {
// TODO Auto-generated method stub
System.out.println("Sorry, gumball has sold out.");
}
}
public class SoldState implements State{
transient GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
// TODO Auto-generated constructor stub
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
// TODO Auto-generated method stub
System.out.println("Wait, we already give you a gumball.");
}
@Override
public void ejectQuarter() {
// TODO Auto-generated method stub
System.out.println("Sorry, you already turned the crank.");
}
@Override
public void turnCrank() {
// TODO Auto-generated method stub
System.out.println("Tunring twice doesn't give you another gunball.");
}
@Override
public void dispense() {
// TODO Auto-generated method stub
gumballMachine.releaseBall();
if (gumballMachine.count > 0) {
gumballMachine.setstate(gumballMachine.noquarterstate);
} else {
System.out.println("Oops. out of gumball.");
gumballMachine.setstate(gumballMachine.soldoutstate);
}
}
}
(3)采用rmi技术实现一个远程服务
import java.rmi.server.*;
import java.rmi.*;
public class GumballMachine extends UnicastRemoteObject implements GumballMachineRemote{
State soldstate;
State soldoutstate;
State noquarterstate;
State hasquarterstate;
State state = soldoutstate;
String location;
int count = 0;
public GumballMachine(String location,int numberGumball) throws RemoteException {
soldstate = new SoldState(this);
soldoutstate = new SoldOutState(this);
noquarterstate = new NoQuarterState(this);
hasquarterstate = new HasQuarterState(this);
this.count = numberGumball;
this.location = location;
if (numberGumball > 0) {
state = noquarterstate;
}
}
public void insertQuarter(){
state.insertQuarter();
}
public void ejectQuarter(){
state.ejectQuarter();
}
public void turnCrank(){
state.turnCrank();
state.dispense();
}
public void setstate(State state){
this.state = state;
}
public void releaseBall(){
System.out.println("A gumball comes rolling out the slot...");
if (count > 0) {
count = count - 1;
}
}
public String toString() {
return "count = " + this.count;
}
public String getLocation() {
return location;
}
public int getCount() {
return count;
}
@Override
public State getState() throws RemoteException {
// TODO Auto-generated method stub
return state;
}
}
(4)采用rmi技术创建客户端
public class GumballMonitor {
GumballMachineRemote machine;
public GumballMonitor(GumballMachineRemote machine) {
this.machine = machine;
}
public void report() {
try {
System.out.println("Gumball Machine: " + machine.getLocation());
System.out.println("Current inventory: " + machine.getCount() + " gumballs");
System.out.println("Current state: " + machine.getState());
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(5)测试代码
服务端:
import java.rmi.Naming;
import java.rmi.RemoteException;
public class GumballMachineTestDrive {
public static void main(String[] args) {
GumballMachine gumballMachine = null;
int count;
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.bind("//" + args[0] + "/gumballmachine", gumballMachine);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//GumballMonitor monitor = new GumballMonitor(gumballMachine);
//monitor.report();
}
}
客户端:
public class GumballMonitorTestDirve {
public static void main(String[] args) {
String[] location = {"rmi://snatafe.mightygumball.com/gumballmachine",
"rmi://boulder.mightygumball.com/gumballmachine",
"rmi://seattle.mightygumball.com/gumballmachine" };
GumballMonitor[] monitor = new GumballMonitor[location.length];
for (int i = 0; i < location.length; i++) {
try {
GumballMachineRemote machine = (GumballMachineRemote) Naming.lookup(location[i]);
monitor[i] = new GumballMonitor(machine);
System.out.println(monitor[i]);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (int i = 0; i < monitor.length; i++) {
monitor[i].report();
}
}
}
2.虚拟代理控制访问创建开销大的资源。
(1)创建一个icon接口,用于图片显示
import java.awt.Component;
import java.awt.Image;
import java.awt.Graphics;
public interface Icon {
public int getIconWidth();
public int getIconHeight();
public void paintIcon(final Component c, Graphics g, int x, int y);
}
(2)继承icon接口,实现具体的icon代理类
import java.awt.Component;
import java.awt.Graphics;
import java.net.URL;
import javax.swing.ImageIcon;
public class ImageProxy implements Icon{
ImageIcon imageIcon;
URL imageURL;
Thread retrievalThread;
boolean retrieving = false;
public ImageProxy(URL url) { imageURL = url; }
@Override
public int getIconWidth() {
// TODO Auto-generated method stub
if ( imageIcon != null) {
return imageIcon.getIconWidth();
} else {
return 800;
}
}
@Override
public int getIconHeight() {
// TODO Auto-generated method stub
if (imageIcon != null) {
return imageIcon.getIconHeight();
} else {
return 600;
}
}
@Override
public void paintIcon(final Component c, Graphics g, int x, int y) {
// TODO Auto-generated method stub
//imageIcon = new ImageIcon("/home/zhangzhilin/eclipse/workspace/ProxyPattern/src/com/zhangzl/virtualproxy/download.jpg", "Cd cover");
//System.out.println("Image description: " + imageIcon.getDescription());
//imageIcon.paintIcon(c, g, x, y);
if (imageIcon != null) {
imageIcon.paintIcon(c, g, x, y);
} else {
g.drawString("Loading CD cover, please wait...", x+50, y+50);
if (!retrieving) {
retrieving = true;
retrievalThread = new Thread(new Runnable() {
public void run() {
try {
imageIcon = new ImageIcon(imageURL, "Cd Cover");
System.out.println("get cd cover success......");
System.out.println("Image width: " + imageIcon.getIconWidth() + ", Image height: " + imageIcon.getIconHeight());
c.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}
});
retrievalThread.start();
}
}
}
}
(3)创建相应的java UI组件显示图片
class ImageComponent extends JComponent{
/**
*
*/
private static final long serialVersionUID = 1L;
private Icon icon;
public ImageComponent(Icon icon){
this.icon = icon;
}
public void paintComponent (Graphics g){
System.out.println("paintComponent");
if(icon == null) return;
int width = icon.getIconWidth();
int height = icon.getIconHeight();
icon.paintIcon(this, g,0,0);
}
}
class ImageFrame extends JFrame{
public ImageFrame(){
setTitle("VirtualProxy");
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
public static final int DEFAULT_WIDTH = 300;
public static final int DEFAULT_HEIGHT = 200;
}
(4)测试代码
import java.net.URL;
import javax.swing.JFrame;
public class ImageProxyTestDrive {
ImageComponent imageComponent;
ImageFrame frame;
//路径自定义
final URL initialURL = new URL("https://timgsa.baidu.com/timg?image&quality=80&si"
+ "ze=b9999_10000&sec=1518093101852&di=ce1984a338845fa88a7eabab0cbfe572&imgtype=0&s"
+ "rc=http%3A%2F%2Fg.hiphotos.baidu.com%"
+ "2Fimage%2Fpic%2Fitem%2Fc8ea15ce36d3d539f09733493187e950342ab095.jpg");
public static void main (String[] args) throws Exception {
ImageProxyTestDrive testDrive = new ImageProxyTestDrive();
}
public ImageProxyTestDrive() throws Exception {
Icon icon = new ImageProxy(initialURL);
imageComponent = new ImageComponent(icon);
frame = new ImageFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.getContentPane().add(imageComponent);
}
}
3.保护代理基于权限控制对资源的访问。
(1)创建一个personBean接口,用来存储个人信息
public interface PersonBean {
String getName();
String getGender();
String getInterests();
int getHotOrNotRating();
void setName(String name);
void setGender(String gender);
void setInterests(String interests);
void setHotOrNotRating(int rating);
}
(2)继承personBean接口,创建具体的personBeanImpl类
public class PersonBeanImpl implements PersonBean{
String name;
String gender;
String interests;
int rating;
int ratingCount = 0;
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
@Override
public String getGender() {
// TODO Auto-generated method stub
return gender;
}
@Override
public String getInterests() {
// TODO Auto-generated method stub
return interests;
}
@Override
public int getHotOrNotRating() {
// TODO Auto-generated method stub
if (ratingCount == 0) return 0;
return (rating/ratingCount);
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
this.name = name;
}
@Override
public void setGender(String gender) {
// TODO Auto-generated method stub
this.gender = gender;
}
@Override
public void setInterests(String interests) {
// TODO Auto-generated method stub
this.interests = interests;
}
@Override
public void setHotOrNotRating(int rating) {
// TODO Auto-generated method stub
this.rating += rating;
ratingCount++;
}
}
(3)利用java的InvocationHandler机制创建两个提供给不同权限用户的代理
//非本人访问者
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class NonOwnerInvocationHandler implements InvocationHandler{
PersonBean person;
public NonOwnerInvocationHandler(PersonBean person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
// TODO Auto-generated method stub
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
method.invoke(person, args);
} else if (method.getName().startsWith("set")) {
throw new IllegalAccessException();
}
}catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
//本人访问
import java.lang.reflect.*;
public class OwnerInvocationHandler implements InvocationHandler {
PersonBean person;
public OwnerInvocationHandler(PersonBean person) {
this.person = person;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException {
// TODO Auto-generated method stub
try {
if (method.getName().startsWith("get")) {
return method.invoke(person, args);
} else if (method.getName().equals("setHotOrNotRating")) {
throw new IllegalAccessException();
} else if (method.getName().startsWith("set")) {
return method.invoke(person, args);
}
}catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
(4)测试代码
import java.lang.reflect.Proxy;
public class MatchMakingTestDrive {
public static void main(String[] args) {
MatchMakingTestDrive test = new MatchMakingTestDrive();
test.drive();
}
public MatchMakingTestDrive() {
//initializeDatabase();
}
public void drive() {
PersonBean joe = new PersonBeanImpl();
joe.setName("joe");
joe.setGender("male");
joe.setInterests("sport");
PersonBean ownerProxy = getOwnerProxy(joe);
System.out.println("Name is " + ownerProxy.getName());
ownerProxy.setInterests("Bowling Go");
System.out.println("Interests set from owner proxy");
try {
ownerProxy.setHotOrNotRating(10);
} catch (Exception e) {
System.out.println("Can't set rating from owner proxy");
}
System.out.println("Rating is " + ownerProxy.getHotOrNotRating());
PersonBean nonOwnerProxy = getNonOwnerProxy(joe);
System.out.println("Name is " + nonOwnerProxy.getName());
try {
nonOwnerProxy.setInterests("boiling, Go");
} catch (Exception e) {
System.out.println("Can't set interests from non owner proxy");
}
nonOwnerProxy.setHotOrNotRating(3);
System.out.println("Rating set from non owner proxy");
System.out.println("Rating is " + nonOwnerProxy.getHotOrNotRating());
}
PersonBean getOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new OwnerInvocationHandler(person));
}
PersonBean getNonOwnerProxy(PersonBean person) {
return (PersonBean) Proxy.newProxyInstance(
person.getClass().getClassLoader(),
person.getClass().getInterfaces(),
new NonOwnerInvocationHandler(person));
}
}