Headfirst java设计模式-代理模式

代理模式:为另一个对象提供一个替身或占位符以控制对这个对象的访问。
代理控制访问的方式:
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接口,用来存储个人信息

扫描二维码关注公众号,回复: 2599849 查看本文章
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));
    }
}

猜你喜欢

转载自blog.csdn.net/MoonShinesOnMyWay/article/details/81367575
今日推荐