• 延迟加载与单例模式


    延迟加载,也较延迟实例化,延迟初始化等,主要表达的思想就是,把对象的创建延迟到使用的时候创建,而不是对象实例化的时候创建。这种方式避免了性能的浪费。

    当创建一个对象的子对象开销比较大时,而且有可能在程序中用不到这个子对象,那么久可以考虑用延迟加载的方式来创建子对象。另外就是当一个程序启动时,需要创建多个对象,但仅有几个对象需要立即使用,那么可以将一些不必要的初始化工作延迟到使用的时候。这样可以提高程序的启动速度。

    FramWork4.0中提供了一个包装类Lazy<T>,可以轻松实现延迟加载。

    今天就先从延迟加载开始学起。

    一、延迟加载

    1Class Singleton

    {

            private static Singleton instance;
          private Singleton()
          { }

          public static Singleton getInstance()

          {

             If(instance==null)

    {

     Instance=new Singleton();

    }

    Return instance;

    }

    }

    构造函数私有,方法静态。

    问题:无法保证线程安全,当有多个线程同时访问getInstance的时候,此时若对象为空,就会出现会多个线程同时产生多个Singleton对象。

    此时我们可以修改一下上面的代码,如下

        public class Singleton
        {  
          
    private static Singleton instance;
          
    private static object _lock=new object();

          
    private Singleton()
           {

           }

          
    public static Singleton GetInstance()
           {
                  
    if(instance==null)
                   {
                         
    lock(_lock)
                          {
                                
    if(instance==null)
                                {
                                         instance
    =new Singleton();
                                 }
                          }
                   }
                  
    return instance;
           }
        }

    上述代码使用了双重锁方式较好地解决了多线程下的单例模式实现。先看内层的if语句块,使用这个语句块时,先进行加锁操作,保证只有一个线程可以访问该语句块,进而保证只创建了一个实例。再看外层的if语句块,这使得每个线程欲获取实例时不必每次都得加锁,因为只有实例为空时(即需要创建一个实例),才需加锁创建,若果已存在一个实例,就直接返回该实例,节省了性能开销。

    2、如果使用如下的单例模式

    class Singleton
    {
     private static Singleton instance = new Singleton();
     private Singleton()
     {
        //
     }
     public static Singleton getInstance()
     {
        return instance;               
     }
    }

    这个方法保证了在第一次加载的时候实例被初始化,且保证了线程安全。但是为进一步要求,我们想要在使用的时候才才初始化Singleton对象,及延迟加载。那么可以使用如下方法。

    3、延迟加载

    public class Singleton {
        private Singleton(){
        }
       private static class SingletonHolder

     {
         static Singleton instance = new Singleton();
        }
        public static Singleton getInstance() {
            return SingletonHolder.instance;
        }
        public static void main(String [] args)
        {
            Singleton.getInstance();
        }
    }

    方法中Singleton 有一个静态内部类SingletonHolder,内部类在外部加载的时候并不会加载,在有在调用getInstance才回加载。另外SingletonHolder类使用Private修饰以确保外部类不能访问。

    二、下面再看一个实例

    namespace WebApplication2

    {

     

        public partial class _Default : System.Web.UI.Page

        {

          

            protected void Page_Load(object sender, EventArgs e)

            {

                // 从数据库中取出数据,得到一个DateRow或者DateRader之类的东东然后初始化一个文章实体类对象

                Model_Article at = 。。。。;//at=getobject();

                // 创建文章分类数据访问对象

                DAO_ArticleCategory articleCategory = new DAO_ArticleCategory();

                subArticle sarticle = new subArticle();

                sarticle.CategoryLazyLoader = articleCategory.GetArticleCategoryById;

                sarticle.CategoryLazyLoader(1);

                Model_ArticleCategory acc = at.Category;

                //

            }

     

        }

        // 文章分类实体类   

        public class Model_ArticleCategory

        {      

            public int CategoryID { get; set; }     

            public string CategoryName { get; set; }  

        }

        public class DAO_ArticleCategory

        {

            public Model_ArticleCategory GetArticleCategoryById(int i)

            {

                return new Model_ArticleCategory();

            }

        }

        // 文章实体类   

        public class Model_Article

        {       

            public int ArticleID { get; set; } 

            public string Title { get; set; }       

            public string Cotnent{ get; set; }       

            public DateTime CreateTime { get; set; }      

            public int CategoryID { get; set; }     

            // 文章所属分类  

            protected Model_ArticleCategory _category;

            public virtual Model_ArticleCategory Category //声明为虚属性

            {

                get

                {

                   

                    GetCategoryRecord += "获取分类;";

                    return _category;

                }

               

            }

            public string GetCategoryRecord { get; set; }

     

        }

        //继承父类,把原来父类中得逻辑放到子类中来实现,保证了父类所处Model层没有引用其他业务层,保证了框架的规则

        public class subArticle : Model_Article

        {

            public override Model_ArticleCategory Category

            {

                get

                {

                    if (base._category == null)

                    {

                        if (CategoryLazyLoader != null)

                        {

                            _category = CategoryLazyLoader(CategoryID);

                        }

                        else

                        {

                            _category = null;

                        }   

                    }

                    return base.Category;

                }

            }

            // 文章分类延时加载器(委托)      

            public Func<int, Model_ArticleCategory> CategoryLazyLoader { get; set; }

        }

      

    }

    基类的Category属性通过返回_category字段的方式返回值,也就是说数据是存在_category字段而不是属性中,但是_category字段怎么才会有值呢,那就是在子类里面通过调用委托拿来的,而这个属性在子类里面不是直接返回的,而是调用基类来返回,这样一来,调用到子类的Category属性的get访问器的时候,先对基类的_categoty字段赋值,然后调用基类的Category属性执行了一些逻辑代码,最后成功地把(已经被赋值的)基类的_categoty字段给返回去。而这一切都是在前面我们实现好的延迟加载的基础上完成的。总结成几个字就是:子类负责延时加载,基类赋值数据存储和返回!

  • 相关阅读:
    hdu 5976 Detachment
    poj 2096 Collecting Bugs
    hdu 4544 湫湫系列故事——消灭兔子
    Educational Codeforces Round 8 B. New Skateboard
    python 迭代器与生成器 区别
    【机器学习】EM算法详细推导和讲解
    【机器学习】极大似然估计详解
    标准sql工单模板
    【机器学习】LDA 浅谈
    Jupyter notebook入门教程
  • 原文地址:https://www.cnblogs.com/yidianfeng/p/2239246.html
Copyright © 2020-2023  润新知