zoukankan      html  css  js  c++  java
  • 延迟加载的原理与代理模式

    前言:

    本篇涉及的代码由C#语言描述,但并不妨碍其他语言的面向对象设计师阅读,旨在理解O/RM延迟加载的原理,减少开发者出现由O/RM引起的性能问题时大叫“怎么会这样?”的几率。

    本篇并不会详细介绍代理模式,也不详细介绍延迟加载,因为这并不是本篇的重点。

    本篇随笔的重点是帮助理解延迟加载的原理,透过这个原理,我们将会知道为什么Nhibernate(O/RM)的领域模型的成员都需要加上virtual关键字,也能更好地理解Nhibernate的延迟加载(当然我相信很少会不借助框架而纯手工去实现延迟加载)。

    我们先来看一个非常简单的例子:

    这个Class1我就暂且当它是一个领域模型,属性Name是我们需要观察的延迟加载成员,而ShowStatus是帮助我们观察延迟加载的状态。

    Class1
    public class Class1
        {
            public virtual string Name { get; set; }
    
            public virtual bool ShowStatus { get; set; }
        }

    这个Class1Proxy是代理类,我们重写而来ShowStatus是为了输出状态,可以看到我们用override重写了Name的Get访问器。

    Class1Proxy
    internal class Class1Proxy:Class1
        {
            private bool _nameLoaded = false;
    
            public override bool ShowStatus
            {
                get { return _nameLoaded; }
            }
    
    
            public override string Name
            {
                get
                {
                    string name;
                    if (!_nameLoaded)
                    {
                        name = "name was loaded";   //模拟从数据库加载数据
                        _nameLoaded = true;
                        base.Name = name;   //当做缓存
                    }
                    else
                    {
                        name = base.Name;   //已经加载的情况加使用缓存
                    }
                    return name;
                }
    
                set
                {
                    base.Name = value;
                    _nameLoaded = true;
                }
            }
        }

    暂时用Mapping类来充当持久化的过程,注意实例化的时候其实是持久化了Proxy,而实际使用当中你不会察觉到你用的是Class1Proxy而不是Class1。

    Mapping
        public class Mapping
        {
            public Class1 Build()
            {
                Class1 c1 = new Class1Proxy();
                return c1;
            }
        }

    测试代码如下,由于我台式机的IDE正好发生了问题,所以就没有使用测试框架,直接输出吧。

    VIEW
    Class1 c1 = new Class1();
                Mapping mapping = new Mapping();
                c1=mapping.Build();
                Response.Write(c1.ShowStatus+"<br/>");
                Response.Write(c1.Name + "<br/>");
                Response.Write(c1.ShowStatus + "<br/>");

    输出结果:

    False
    name was loaded
    True

    结果可以看到,刚持久化以后Name并没有被加载(可以看到Mapping.Build方法中并没有持久化Name),所以输出了False,然后客户端试着输出c1.Name,也就在这时才开始加载Name,然后我们发现输出时Name已经有数据了。

    讨论:

    在这个例子当中使用了一个简单的代理,正是因为virtual关键字,使得延迟加载得以实现,而实际上在java中所有成员默认就是virtual的,所以在Hibernate中并不需要加这个关键字,并不是因为Nhibernate在移植过程中残疾了,而是本该如此。

    如果使用Nhibernate时放弃延迟加载的功能择可以不必设置动态代理,也就可以不必处处加上virtual关键字,但在领域驱动设计中这并不是个好主意。

    最后感谢你可以看到这里,希望本篇的介绍会对你有所帮助。

  • 相关阅读:
    第一个python的GUI程序
    vbs实现打开记事本,写入一些文字,复制然后关闭
    自己制作的autoitX的vbs脚本,用来自动配置金山毒霸2011局域网更新
    使用免费的unrar.exe解压rar文件
    初学写的几个autoit小程序
    vba调用AutoItX3的Activex控件,实现doc2Html源码
    网页制作相关工具
    vbs自动登陆115网盘代码
    深搜和宽搜的c++实现
    入职一个月有感
  • 原文地址:https://www.cnblogs.com/13yan/p/3026864.html
Copyright © 2011-2022 走看看