代理模式(Proxy Pattern)之虚拟代理

来源:互联网 发布:女生围巾推荐 知乎 编辑:程序博客网 时间:2024/04/28 19:44

虚拟代理作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,有虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。


场景:利用虚拟代理实现WINFORM加载URL图片,要求加载过程有文字提示并且不能另窗体保持可响应状态。

//为代理创建一个接口

    //代理接口    public interface IIcon    {        void paintIcon(Control control, PaintEventArgs e, int x, int y);    }
//为加载图片创建代理

    public class ImageProxy :IIcon    {        //存储图片的对象        Image imageIcon;        //图片URL对象        Uri imageURL;        //处理图片加载的线程        Thread retrievalThread;        //是否在线程过程中        Boolean retrieving = false;        public ImageProxy(string url)        {            imageURL = new Uri(url);        }        public void paintIcon(Control control, PaintEventArgs e, int x, int y)        {            if (imageIcon != null)            {                //绘制图片                e.Graphics.DrawImage(imageIcon, x, y);            }            else            {                FontFamily myFontFamily = new FontFamily("宋体");                Font font = new Font(myFontFamily, 20, FontStyle.Regular);                //绘制提示字符                control.CreateGraphics().DrawString("Loading CD cover, please wait...", font, Brushes.Black, x + 100, y + 190);                if (!retrieving)                {                    retrieving = true;                    retrievalThread = new Thread(() =>                    {                        try                        {                            //通过URL获取图片                            imageIcon = getUriPictrue(imageURL);                            //重新绘制输入的控件                            control.Invalidate();                        }                        catch (Exception error)                        {                            Console.WriteLine(error.StackTrace);                        }                    });                    retrievalThread.Start();                }            }        }        private Image getUriPictrue(Uri uri)        {            WebRequest webreq = WebRequest.Create(uri);            WebResponse webres = webreq.GetResponse();            using (Stream stream = webres.GetResponseStream())            {                return Image.FromStream(stream);            }        }    }
//自定义Panel控件
    class MyPanel:System.Windows.Forms.Panel    {        IIcon imageLoad=null;        public void bindIcon(IIcon imageLoad)        {            this.imageLoad = imageLoad;        }        //当调用该Panel的Control.nvalidate()时,发生该事件        protected override void OnPaint(PaintEventArgs e)        {            if (imageLoad != null)            {                imageLoad.paintIcon(this,e, 0, 0);            }            base.OnPaint(e);        }    }

//窗体程序

    public partial class Form1 : Form    {        public Form1()        {            InitializeComponent();        }        IIcon imageLoad;        private void button1_Click(object sender, EventArgs e)        {            imageLoad = new ImageProxy(textBox1.Text);            this.panel1.bindIcon(imageLoad);            imageLoad.paintIcon(panel1, null, 0, 0);        }       }
//测试程序

    class Program    {        static void Main(string[] args)        {            Application.EnableVisualStyles();            Application.SetCompatibleTextRenderingDefault(false);            Application.Run(new GUI.Form1());        }    }
//测试结果:

//加载中


//加载完成


总结:

1.代理的变体都有共通点:都会将客户对主题施加的方法调用拦截下来。这种间接的级别让我们可以做许多事。

2.装饰者是为对象增加行为,而代理是控制对象的访问。本例中FORM将显示在PANEL里的图像完全交给ImageProxy,让主程序与imageIcon解耦进而不用关心对其的操作过程。

3.一个常用的技巧是提供一个工厂,实例化并返回主题。因为这是在工厂方法内发生的,我们可以用代理包装主题再返回。

4.虽然都是挡在其他对象前面,但适配器会改变对象适配的接口,而代理则实现相同的接口。


0 0
原创粉丝点击