代理模式——虚拟代理(二)

代理模式定义
为另一个对象提供一个替身或占位符以控制对这个对象的访问。使用代理模式创建代表对象,让代表对象控制对某对象的访问,被代理的对象可是远程的对象、创建开销大的对象或需要安全控制的对象。

代理分三种:

1.远程代理,帮助我们控制访问远程对象:
远程代理可以作为另一个JVM上对象的本地代表。调用代理的方法,会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。
2.虚拟代理,帮助我们控制访问创建开销大的资源
虚拟代理作为创建开销大的对象的代表,经常会直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理地来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。
3.保护代理,基于权限控制对资源的访问。

本篇讲一讲虚拟代理:
虚拟代理用于隐藏开销大的对象,如我们需要通过网络取得图像数据。
在这里插入图片描述
ImageProxy的工作过程:

  1. ImageProxy首先创建一个ImageIcon,然后开始从网络URL上加载图像
  2. 在加载过程中,ImageProxy显示占位图
  3. 当图像加载完毕,ImageProxy把所有方法调用都委托给真正的ImageIcon,这些方法包括getIconHeight()、getIconWidth()、paintIcon()。
  4. 如果用户请求请的图像,我们就创建新的代理,重复这样的过程。

Icon接口:

public interface Icon {
    int getIconWidth();
    int getIconHeight();
    void paintIcon(ImageView imageView);
}

ImageProxy代码:

public class ImageProxy implements Icon {

    ImageIcon imageIcon; //这是加载后显示出来的真正图像
    URL imageURL;  //真正图像的URL
    Thread retrievalThread;
    boolean retrieving = false;
    Bitmap bitmap;//占位图
    ImageView imageView;显示图片的容器



    private Handler refresh = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            ImageProxy.this.paintIcon(imageView);
        }
    };


    public ImageProxy(URL url,Bitmap bitmap){
        this.imageURL = url;  
        this.bitmap = bitmap;

    }


    @Override
    public int getIconWidth() {
        if(imageIcon != null){
            return imageIcon.getIconWidth();
        }else{
            return 800;
        }

    }

    @Override
    public int getIconHeight() {
        if(imageIcon != null){
            return imageIcon.getIconHeight();
        }else{
            return 600;
        }
    }

    @Override
    public void paintIcon(ImageView imageView) {

        this.imageView = imageView;

        if(imageIcon != null){
            imageIcon.paintIcon(imageView);
        }else{

            imageView.setImageBitmap(bitmap);

            if(!retrieving){
                retrieving = true;
                retrievalThread = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if(imageURL != null){
                            try {
                                HttpURLConnection conn = (HttpURLConnection) imageURL.openConnection();
                                conn.setDoInput(true);
                                conn.connect();
                                InputStream is = conn.getInputStream();
                                Bitmap bitmap1 = BitmapFactory.decodeStream(is);
                                imageIcon = new ImageIcon(bitmap1);
                                is.close();
                                refresh.sendEmptyMessage(1); //图像加载完成后,自动刷新
                            }catch (Exception e){
                                e.printStackTrace();
                            }
                        }
                    }
                });
                retrievalThread.start();
            }

        }
    }
}

ImageIcon代码:

public class ImageIcon implements Icon {
    Bitmap bitmap;

    public ImageIcon(Bitmap bitmap) {
        this.bitmap = bitmap;
    }


    @Override
    public int getIconWidth() {
        if (bitmap != null) {
            return bitmap.getWidth();
        }
        return 0;
    }

    @Override
    public int getIconHeight() {
        if (bitmap != null) {
            return bitmap.getHeight();
        }
        return 0;
    }

    @Override
    public void paintIcon(ImageView imageView) {

        if (imageView != null && bitmap != null) {
            imageView.setImageBitmap(bitmap);
        }
    }
}

ImageProxy控制ImageIcon的访问。代理将客户从ImageIcon解耦了,如果它们之间没有解耦,客户就必须等到每幅图像都被取回,然后才能把它绘制到界面上。

代理模式有很多变体,这些变体都有一个共通点:都会将客户对主题(subject)施加的方法调用拦截下来。这种间接的级别让我们可以做很多事,包括将请求分发到远程主题;给创建开销大的对象提供代表;提供某些级别的保护,这种保护能决定哪些客户能调用哪些方法

这里要与装饰者区分开,装饰者为对象增加行为,而代理是控制对象的访问。

最后分享Demo代码

谢谢阅读!有兴趣可以前往《代理模式——保护代理(三)》进行阅读。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值