• Java设计模式十八:代理模式(Proxy)


    为另一个对象提供一个替身或占位符以控制对这个对象的访问,简而言之就是用一个对象来代表另一个对象。
    类图:


    简单例子:有个接口Italk,people对象实现这个接口的talk()方法,有些想另外加入sing()方法,所以增加代理类talkProxy,实现两个方法.
    public interface ITalk
    {
        public void talk(String msg);
    }

    public class People implements ITalk
    {
        @Override
        public void talk(final String msg)
        {
            System.out.println(msg);
        }
    }

    public class TalkProxy implements ITalk
    {
        ITalk italk;

        public TalkProxy(final ITalk italk)
        {
            this.italk = italk;
        }

        @Override
        public void talk(final String msg)
        {
            this.italk.talk(msg);
        }

        public void sing(final String songName)
        {
            System.out.println("Song Name:" + songName);
        }
    }

    public class Client
    {
        public static void main(final String[] args)
        {
            final People people = new People();
            people.talk("I can't sing");

            final TalkProxy proxy = new TalkProxy(people);
            proxy.talk("I can talk");
            proxy.sing("I can sing");
        }
    }

    结果:
    I can't sing
    I can talk
    Song Name:I can sing

    常见的代理:
    1. 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以是在同一台主机中,也

    可是在另一台主机中,远程代理又叫做大使(Ambassador)。
    import java.rmi.Remote;
    import java.rmi.RemoteException;
    public interface MyRemote extends Remote
    {
        public String getUserName(String userId) throws RemoteException;
    }

    import java.rmi.RemoteException;
    import java.rmi.server.UnicastRemoteObject;
    public class MyRemoteImp extends UnicastRemoteObject implements MyRemote
    {
        protected MyRemoteImp() throws RemoteException
        {
            
        }

        public String getUserName(String userId) throws RemoteException
        {
            return userId + "/myName is Cherry";
        }

    }

    在cmd中输入:
    javac MyRemote.java
    javac MyRemoteImp.java
    rmic MyRemoteImp
    生成类的class文件及MyRemoteImp_Stub.class文件


    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.RemoteException;
    public class MyRemoteServer
    {
        public static void main(final String[] args)
        {
            // YTODO Auto-generated method stub
            MyRemote remote;
            try
            {
                remote = new MyRemoteImp();
                Naming.rebind("RemoteService", remote);
            }
            catch (final RemoteException e)
            {
                // YTODO Auto-generated catch block
                e.printStackTrace();
            }
            catch (final MalformedURLException e)
            {
                // YTODO Auto-generated catch block
                e.printStackTrace();
            }

        }

    }

    import java.net.MalformedURLException;
    import java.rmi.Naming;
    import java.rmi.NotBoundException;
    import java.rmi.RemoteException;
    public class MyRemoteClient
    {
        public static void main(final String[] args)
        {
            try
            {
                final MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/RemoteService");
                final String name = service.getUserName("my id is 001");
                System.out.println(name);
            }
            catch (final MalformedURLException e)
            {
                e.printStackTrace();
            }
            catch (final RemoteException e)
            {
                e.printStackTrace();
            }
            catch (final NotBoundException e)
            {
                e.printStackTrace();
            }
        }

    }

    在dos下运行rmiregistry, 这个命令是开启RMI注册服务, 开启以后我们的server程序才能调用rebing方法发布我们的类,然后运行server程序

    .
    javac MyRemoteServer.java
    java MyRemoteServer

    start rmiregistry
    javac MyRemoteServer.java
    java MyRemoteServer

    再打开一个dos运行客户端代码
    javac MyRemoteClient.java
    java MyRemoteClient

    输出:my id is 001/myName is Cherry

    这里一共有三个dos窗口, 当执行start rmiregistry时,会弹出它的窗口,当执行java MyRemoteServer的服务器端窗口,执行java

    MyRemoteClient的客户端窗口(这里的rmiregistry.exe的窗口需要一直打开,否则无法调用服务器端).

    2. 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表

    示,真实对象只会在需要时才会被真正创建。
    public interface Image
    {
        public void show();
    }

    public class BigImage implements Image
    {
        public BigImage()
        {
            //Thread.sleep(3000);//for simulating to load the big images
            System.out.println("create the big images");
        }

        @Override
        public void show()
        {
            System.out.println("show the big images");
        }
    }

    public class ImageProxy implements Image
    {
        Image image;

        public ImageProxy()
        {

        }

        public ImageProxy(final Image image)
        {
            this.image = image;
        }

        @Override
        public void show()
        {
            if (this.image == null)
            {
                this.image = new BigImage();
            }
            this.image.show();
        }
    }

    public class Client
    {
        public static void main(final String[] args)
        {
            System.out.println("big image:");
            final Image bigImage = new BigImage();
            bigImage.show();

            System.out.println("image proxy:");
            final Image imageProxy = new ImageProxy();
            imageProxy.show();
        }
    }
    结果:
    create the big images
    show the big images
    image proxy:
    create the big images
    show the big images

    3. Copy-on-Write代理: 虚拟代理的一种,把复制(克隆)拖延到只有在客户端需要时,才真正采取行动。

    4. 保护代理(Protection or Access Proxy):控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。

    5. 智能指引(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作.

  • 相关阅读:
    初识python
    文件操作
    初识python
    pycharm IDE
    初识python
    初识Python
    python之网络编程-多线程
    python之并发编程-进程之间的通信
    python之并发编程-多进程
    python之并发编程-操作系统
  • 原文地址:https://www.cnblogs.com/itTeacher/p/2818572.html
Copyright © 2020-2023  润新知