zoukankan      html  css  js  c++  java
  • How to Cache an Object(转载)

    For performance efficiency, you may wish to cache an object within another object. That sounds easy enough to do. But what if the object cannot be found? You have to take special care to ensure the object is not fetched repeatedly.

    An Example

    As always, the best way to demonstrate this is with an example. Consider a "Company" object that has a GetEmployee method which retrieves an Employee object from a remote database, an operation that could take a few seconds. There is also a CEO property that returns the Employee object representing the company's CEO:

    public class Company
    {
    public Employee CEO
    {
    get
            {
    // ...
            }
    }
    public Employee GetEmployee( Roles role )
    {
    // ...
        }
    }

    Cached Object

    To improve performance, let's say we want to cache the Employee object returned by the CEO property so that it can be accessed repeatedly with no delay after the first access. The easiest way to do this is simply include a private member that holds the CEO object once it has been loaded:

    private Employee m_CEO;
    public Employee CEO
    {
    get
        {
    if (this.m_CEO == null)
    this.m_CEO = this.GetEmployee( Roles.CEO );
    return this.m_CEO;
    }
    }

    So far so good. But what if the CEO object cannot be found? As written above, the CEO property will call the GetEmployee method every time, resulting in a significant performance penalty.

    Improved Cache

    The solution is to create a blank Employee object and save it in a static member. As shown below, the Employee object stored in the s_EmployeeNotFound static member will serve as a "flag" to indicate that we've already attempted to get the CEO object but failed, hence do not attempt to get it again. If the CEO object could not be retrieved, instead of leaving the cached m_CEO reference as null, we set it equal to the s_EmployeeNotFound reference to indicate that we've already tried to load the CEO, so don't bother doing it again.

    public class Company
    {
    static private Employee s_EmployeeNotFound = new Employee();
    private Employee m_CEO;
    public Employee CEO
    {
    get
            {
    // get the cached CEO
                Employee ceo = this.m_CEO;
    // if no CEO is cached
                if (ceo == null)
    {
    // try to load the CEO
                    ceo = this.GetEmployee( Roles.CEO );
    // if could not load the CEO
                    if (ceo == null)
    {
    // indicate the CEO was not found
                        ceo = s_EmployeeNotFound;
    }
    // cache the new CEO
                    this.m_CEO = ceo;
    }
    // if CEO was not found
                if (Object.ReferenceEquals( ceo, s_EmployeeNotFound ) )
    {
    // indicate there is no CEO to load
                    ceo = null;
    }
    return ceo;
    }
    }

    Note the use of Object.ReferenceEquals to compare objects. This ensures that we are truly checking for our special s_EmployeeNotFound object and prevents any accidental equality from an overridden Equals method in the Employee object.

    Console Test Program

    Using this example, here is a console test program that demonstrates how an object cache can really save time on multiple accesses. For simplicity, the GetEmployee method simply sleeps for 2 seconds to simulate a delay loading the object from a remote database.

    using System;
    namespace CachedObject
    {
    class Program
        {
    static void Main( string[] args )
    {
    Company company = new Company();
    DateTime time1 = DateTime.Now;
    Console.WriteLine( "Accessing CEO for the first time..." );
    Employee ceo = company.CEO;
    DateTime time2 = DateTime.Now;
    Console.WriteLine( "Accessing cached CEO...\n" );
    ceo = company.CEO;
    DateTime time3 = DateTime.Now;
    Console.WriteLine( "Time accessing CEO object:\nNotCached...{0}\nCached......{1}",
    time2.Subtract( time1 ), time3.Subtract( time2 ) );
    Console.ReadLine();
    }
    public class Company
            {
    static private Employee s_EmployeeNotFound = new Employee();
    private Employee m_CEO;
    public Employee CEO
    {
    get
                    {
    // get the cached CEO
                        Employee ceo = this.m_CEO;
    // if no CEO is cached
                        if (ceo == null)
    {
    // try to load the CEO
                            ceo = this.GetEmployee( Roles.CEO );
    // if could not load the CEO
                            if (ceo == null)
    {
    // indicate the CEO was not found
                                ceo = s_EmployeeNotFound;
    }
    // cache the new CEO
                            this.m_CEO = ceo;
    }
    // if CEO was not found
                        if (ceo == s_EmployeeNotFound)
    {
    // indicate there is no CEO to load
                            ceo = null;
    }
    return ceo;
    }
    }
    public Employee GetEmployee( Roles role )
    {
    // simulates a delay due to remote database access, for example
                    System.Threading.Thread.Sleep( 2000 );
    // would return the employee if found; for this test, assume fail
                    return null;
    }
    }
    public class Employee
            {
    public string Name;
    public int ID;
    public Roles Role;
    public DateTime BirthDate;
    public DateTime HireDate;
    }
    public enum Roles
            {
    CEO,
    Management,
    Sales,
    Marketing,
    Development,
    Staff,
    }
    }
    }

    Test Program Output

    And here is the output to the test program. Notice how the first access of the CEO property took two seconds, but the second and all subsequent accesses will take no time at all, even if the CEO object could not be retrieved.

    Accessing CEO for the first time…
    Accessing cached CEO…
    Time accessing CEO object:
    NotCached…00:00:02.0156250
    Cached……00:00:00

    转载自:http://www.csharp411.com/how-to-cache-an-object/

  • 相关阅读:
    Redis基本概念、基本使用与单机集群部署
    Storm安装部署
    HBase单机和集群版部署
    Hive基础概念、安装部署与基本使用
    Hadoop — HDFS的概念、原理及基本操作
    随机森林
    深度学习入门: CNN与LSTM(RNN)
    word修改页眉使本页的页眉与别的页不一样
    几个值得学习的Java博客
    【转】求最短路径长度--简单易懂
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1626542.html
Copyright © 2011-2022 走看看