.NET中的Entity Framework 和 java里面的 Hibernate都是ORM框架,它們中間都用到延時加載,延時加載對于提高性能,減小服務(wù)器內(nèi)存壓力有很大的作用。所謂延時加載,就是只有在第一次調(diào)用某個實體的方法或?qū)傩詴r才初始化該實體。延時加載適用于創(chuàng)建開銷大的對象。如下,我采用代理模式模擬了一個簡單的延時加載的例子。
首先,我定義了一個接口,名為IOperation,定義如下:
1 public interface IOperation
2 {
3 /// <summary>
4 /// 聲明一個描述類信息的方法,由子類實現(xiàn)。
5 /// </summary>
6 void Describe();
7 /// <summary>
8 /// 聲明一個銷毀訂單的操作,由子類操作
9 /// </summary>
10 void DestoryOrder();
11 }然后定義兩個實體類,Product類和Order類,分別表示兩個相互關(guān)聯(lián)的實體,在Product類中注入Order類的變量用以在Product類中調(diào)用Order類的實例方法。并且讓Product類實現(xiàn)IOperate接口。
Product類定義如下:
1 public class Product : IOperation
2 {
3 private Order _order;
4 public Product()
5 {
6 Console.WriteLine(">>開始初始化Product類...");
7 Stopwatch sw = new Stopwatch();
8 sw.Start();
9 this._order = new Order();
10 sw.Stop();
11 Console.WriteLine(">>初始化Product類完成。耗時:{0}秒", sw.ElapsedMilliseconds / 1000);
12 }
13 public void Describe()
14 {
15 Console.WriteLine(">>Product描述:我的是Product類的實例,Describe方法執(zhí)行完成。");
16 }
17 public void DestoryOrder()
18 {
19 Console.WriteLine(">>Product.DestoryOrder()方法開始執(zhí)行...");
20 if (_order != null)
21 {
22 //調(diào)用Order類的Destroy實例方法,銷毀自己。
23 _order.Destroy();
24 Console.WriteLine(">>Product.DestoryOrder()方法執(zhí)行完成。");
25 }
26 }
27 }Order類定義如下:
1 public class Order
2 {
3 public Order()
4 {
5 Console.WriteLine(">>開始初始化Order類...");
6 System.Threading.Thread.Sleep(5000);
7 Console.WriteLine(">>初始化Order類完成。");
8 }
9
10 public void Destroy()
11 {
12 Console.WriteLine(">> Order 已銷毀。");
13 }
14 }然后在主程序里面調(diào)用一下:
1 static void Main(string[] args)
2 {
3 Console.WriteLine("==========不使用代理類調(diào)用Describe()方法===============");
4 Product p = new Product();
5 p.Describe();
6 Console.WriteLine("==========不使用代理類調(diào)用DestoryOrder()方法===============");
7 Product p2 = new Product();
8 p2.DestoryOrder();
9 Console.ReadKey();
10 }>
測試結(jié)果如下:

從上圖中,我們可以看出,調(diào)用Describe()方法初始化Product類用了5秒,這是不是有問題?再看看上面的Describe()方法的實現(xiàn),只簡單的輸出了一句話,怎么會用5秒?再看Product的構(gòu)造函數(shù)里面,在初始化Product類的實例的時候,把Order類也初始化了,但是我這個Describe()方法并沒有調(diào)用Order類的任何方法和屬性,所以這就造成了不必要的內(nèi)存開銷,而且初始化了的Order類的實例也沒有使用,產(chǎn)生了垃圾對象。
怎么解決這個問題呢?所以這個地方就得用代理了,代理是個什么東西呢?代理簡單來說,就是制造一個與被調(diào)對象具有相同功能(這個相同功能通常由接口去規(guī)范)的類,在這個類中可以調(diào)用被調(diào)對象的方法,也可以自定義新的方法供調(diào)用方使用。下面就是代理類的創(chuàng)建。
首先,我創(chuàng)建一個代理類,名為ProxyProduct,讓它也實現(xiàn)IOperate接口,定義如下:
1public class ProxyProduct : IOperation
2{
3 private IOperation entity;
4
5 public ProxyProduct(IOperation entity)
6 {
7 Console.WriteLine(">>開始初始化ProxyProduct...");
8 Stopwatch sw = new Stopwatch();
9 sw.Start();
10 this.entity = entity;
11 sw.Stop();
12 Console.WriteLine(">>初始化ProxyProduct完成。耗時:{0}秒", sw.ElapsedMilliseconds / 1000);
13 }
14 /// <summary>
15 /// 實現(xiàn)IOperation的方法
16 /// </summary>
17 public void Describe()
18 {
19 Console.WriteLine(">>ProxyProduct描述:我的是ProxyProduct類的實例,Describe()方法執(zhí)行完成。");
20 }
21 /// <summary>
22 /// 實現(xiàn)IOperation的方法
23 /// </summary>
24 public void DestoryOrder()
25 {
26 Console.WriteLine(">>ProxyProduct.DestoryOrder()方法開始執(zhí)行...");
27 if (entity == null)
28 {
29 entity = new Product();
30 }
31 entity.DestoryOrder();
32 Console.WriteLine(">>ProxyProduct.DestoryOrder()方法執(zhí)行完成。");
33 }
34}在主程序里面測試一下:
1 static void Main(string[] args)
2 {
3 Console.WriteLine("==========使用代理類調(diào)用Describe()方法===============");
4 IOperation desc = new ProxyProduct(null) as IOperation;
5 if (desc != null)
6 {
7 desc.Describe();
8 }
9 Console.WriteLine("==========使用代理類調(diào)用DestoryOrder()方法===============");
10 IOperation desc2 = new ProxyProduct(null) as IOperation;
11 if (desc2 != null)
12 {
13 desc2.DestoryOrder();
14 }
15 Console.ReadKey();
16 }測試結(jié)果如下:

從上圖看出,調(diào)用Describe()方法時耗時0秒,調(diào)用DestoryOrder()方法時,初始化代理類用了0秒,初始化Product類用了5秒,所以執(zhí)行DestroyOrder()方法一共花費了5秒。這樣的結(jié)果是令人滿意的,使用代理類就實現(xiàn)了“調(diào)用誰的方法,就初始化誰;不調(diào)用不初始化”的想法。這樣的話,如果我永遠(yuǎn)只調(diào)Describe()方法,那么我花費的時間永遠(yuǎn)是0秒,而不會產(chǎn)生額外的開銷,這對性能優(yōu)化有很大的幫助。
總結(jié):代理模式應(yīng)用之一:對于某些創(chuàng)建時需要很大開銷的對象,我們可以使用代理讓這個對象在第一次調(diào)用它的方法或?qū)傩詴r才創(chuàng)建它的實例,不調(diào)用它的方法或?qū)傩詣t永遠(yuǎn)不創(chuàng)建它的實例。好處:性能優(yōu)化,減小內(nèi)存開銷。
==================================================================================================================
如下是java代碼實現(xiàn):
接口:IOperate
1 public interface IOperate {
2 /**
3 * 聲明一個描述類信息的方法,由子類實現(xiàn)。
4 */
5 void describe();
6 /**
7 * 聲明一個銷毀訂單的方法,由子類實現(xiàn)。
8 */
9 void destroyOrder();
10 }
實現(xiàn)類:ProductBean
1 public class ProductBean implements IOperate {
2 private OrdersBean ordersBean;
3
4 /**
5 * 初始化ProductBean類的實例
6 */
7 public ProductBean() {
8 System.out.println(">>開始初始化ProductBean....");
9 long startTime = System.currentTimeMillis();
10 this.ordersBean = new OrdersBean();
11 long endTime = System.currentTimeMillis();
12 System.out.println(">>初始化ProductBean完成。耗時:" + (endTime - startTime) / 1000 + "秒");
13 }
14
15 public void describe() {
16 System.out.println(">>describe描述:我是ProductBean類,執(zhí)行了describe()方法。");
17 }
18
19 public void destroyOrder() {
20 System.out.println(">>開始執(zhí)行ProductBean.destroyOrder()方法...");
21 if (this.ordersBean != null) {
22 this.ordersBean.destroy();
23 System.out.println(">>ProductBean.destroyOrder()方法執(zhí)行完成。");
24 }
25 }
26 }實體類:OrderBean
1 public class OrdersBean {
2 public OrdersBean() {
3 System.out.println(">>開始初始化OrderBean.....");
4 InitOrder();
5 System.out.println(">>初始化OrderBean完成。");
6 }
7
8 /**
9 * 初始化訂單
10 */
11 private void InitOrder() {
12 try {
13 // 加載訂單數(shù)據(jù),這里模擬耗時3秒。
14 Thread.sleep(5000);
15 } catch (Exception e) {
16 e.printStackTrace();
17 }
18 }
19
20 public void destroy() {
21 System.out.println(">> Order 已銷毀。");
22 }
23 }代理類:ProxyProductBean
1 public class ProxyProductBean implements IOperate {
2 private IOperate bean;
3
4 public ProxyProductBean(IOperate bean) {
5 System.out.println(">>開始初始化ProxyProductBean.....");
6 long startTime = System.currentTimeMillis();
7 this.bean = bean;
8 long endTime = System.currentTimeMillis();
9 System.out.println(">>初始化ProxyProductBean完成。耗時:" + (endTime - startTime) / 1000 + "秒");
10 }
11
12 public void describe() {
13 System.out.println(">>describe描述:我是ProxyProductBean類,執(zhí)行了describe()方法。");
14 }
15
16 public void destroyOrder() {
17 System.out.println(">>開始執(zhí)行ProxyProductBean.destroyOrder()方法...");
18 if (bean == null) {
19 bean = new ProductBean();
20 bean.destroyOrder();
21 System.out.println(">>執(zhí)行ProxyProductBean.destroyOrder()方法完成。");
22 }
23 }
24 }測試類:
1 public class Test {
2 public static void main(String[] args) {
3 System.out.println("==========不使用代理類調(diào)用describe()方法===============");
4 ProductBean productBean = new ProductBean();
5 productBean.describe();
6 System.out.println("==========使用代理類調(diào)用describe()方法===============");
7 IOperate description = (IOperate) (new ProxyProductBean(null));
8 description.describe();
9 System.out.println("==========不使用代理類調(diào)用cascadeOperate()方法===============");
10 ProductBean productBean2 = new ProductBean();
11 productBean2.destroyOrder();
12 System.out.println("==========使用代理類調(diào)用cascadeOperate()方法===============");
13 IOperate description2 = (IOperate) (new ProxyProductBean(null));
14 description2.destroyOrder();
15 }
16 }測試結(jié)果輸出如下:
==========不使用代理類調(diào)用describe()方法===============
>>開始初始化ProductBean....
>>開始初始化OrderBean.....
>>初始化OrderBean完成。
>>初始化ProductBean完成。耗時:5秒
>>describe描述:我是ProductBean類,執(zhí)行了describe()方法。
==========使用代理類調(diào)用describe()方法===============
>>開始初始化ProxyProductBean.....
>>初始化ProxyProductBean完成。耗時:0秒
>>describe描述:我是ProxyProductBean類,執(zhí)行了describe()方法。
==========不使用代理類調(diào)用cascadeOperate()方法===============
>>開始初始化ProductBean....
>>開始初始化OrderBean.....
>>初始化OrderBean完成。
>>初始化ProductBean完成。耗時:5秒
>>開始執(zhí)行ProductBean.destroyOrder()方法...
>> Order 已銷毀。
>>ProductBean.destroyOrder()方法執(zhí)行完成。
==========使用代理類調(diào)用cascadeOperate()方法===============
>>開始初始化ProxyProductBean.....
>>初始化ProxyProductBean完成。耗時:0秒
>>開始執(zhí)行ProxyProductBean.destroyOrder()方法...
>>開始初始化ProductBean....
>>開始初始化OrderBean.....






