歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

設計模式之享元模式——初學

1、引言

一些大型的博客網站、電子商務網站,裡面每一個博客或者商家都可以理解為一個小的網站,他們是如何做到的呢,如何實現同樣的核心代碼,不同的用戶用有不同的效果,實現類型的網站得到復用而不是復制相同的代碼呢?

那些博客網站、電子商務網站是利用用戶ID的不同,來區別不同的用戶,具體的數據和模板可以不同,但代碼核心和數據庫卻是共享的。

假如很多項目到來時,他們需要的網站結構相似度很高,而且都不是那種高訪問量的網站,如果分成多個虛擬空間來處理,相當於一個相同網站的實例對象很多,這是造成服務器的大量資源浪費,當然更實際的其實是鈔票的浪費,如果整合到一個網站中,共享其相關的代碼和數據,那麼對於硬盤、內存、CPU、數據庫空間等服務器資源都可以達到共享,減少服務器資源,而對於代碼,由於是一份實例,維護和擴展都更加容易。

好像很不錯的樣子,我也這麼覺得,那我們就一起來了解一下, 如何做到共享一份實例吧。

2、定義:

享元模式(Flyweight),運用共享技術有效地支持大量細粒度的對象。

3、UML(結構圖)

類解析:

FlyWeightFactory:一個共享工廠,用來創建並管理Flyweight對象。它主要是用來確保合理地共享Flyweight,當用戶請求一個Flyweight是,FlyweightFactory對象提供一個已創建得實例或者創建一個(如果不存在的話)

Flyweight:所有具體享元類的超類或接口,通過這個接口,Flyweight可以接受並作用於外部狀態,

ConcreteFlyweight:繼承Flyweight超類或實現Flyweight接口,並為內部狀態增加存儲空間

UnsharedConcreteFlyweight:指那些不需要共享的Flyweight。因為Flyweight接口共享成為可能,但它不強制要求共享。

4、實踐

網站共享代碼

package com.zcr.flyweight;
//享元設計模式實現
//網站抽象類
public abstract class WebSite
{
 public abstract void Use();
}

 

 

 

package com.zcr.flyweight;
//具體的網站類
public class ConcreteWebSite extends WebSite
{
 private String name = "";
 
 public ConcreteWebSite(String name)
 {
  this.name = name;
 }
 
 @Override
 public void Use()
 {
  System.out.println("網站分類:"+name);
 }
}

 

 

 

 

package com.zcr.flyweight;
import java.util.Hashtable;
//網站工廠
public class WebsiteFactory
{
 private Hashtable<String,WebSite> flyweights = new Hashtable<String, WebSite>();
 
 //獲得網站分類
 public WebSite GetWebSiteCategory(String key)
 {
  //判斷是否存在這個對象,如果存在則直接返回,若不存在,則實例化它再返回
  if(!flyweights.contains(key))
  {
  flyweights.put(key, new ConcreteWebSite(key));
  }
  return flyweights.get(key);
 }
 
 //獲取網站分類的總數
 public int GetWebSiteCount()
 {
  return flyweights.size();
 }
}

 

 

 

 

package com.zcr.flyweight;
public class FlyweightTest
{
 public static void main(String[] args)
 {
  WebsiteFactory f = new WebsiteFactory();
 
  WebSite fx = f.GetWebSiteCategory("產品展示");
  fx.Use();
 
  WebSite fy = f.GetWebSiteCategory("產品展示");
  fy.Use();
 
  WebSite fz = f.GetWebSiteCategory("產品展示");
  fz.Use();
 
  WebSite fl = f.GetWebSiteCategory("博客");
  fl.Use();
 
  WebSite fm = f.GetWebSiteCategory("博客");
  fm.Use();
 
  WebSite fn = f.GetWebSiteCategory("博客");
  fn.Use();
 
  System.out.println("網站分類總數為:" + f.GetWebSiteCount());
 }
}

結果:

上面只實現了對象的共享,不管建立幾個網站,是要是‘產品展示’都好是一樣的的,只要是‘博客’也是完全相同的,但這樣是有問題的,你給企業建立的網站不是一家企業,它們的數據不會相同,所以至少它們應該有不同的賬號,那我們該怎麼辦呢?

概念:

內部狀態:在享元內部並且不會隨環境改變而改變的共享部分

外部狀態:隨環境改變而改變的、不可能共享的狀態就是外部狀態

享元模式可以避免大量非常相似類的開銷,在程序設計中,有時需喲生成大量細粒度的類實例來表示數據,如果能發現這些實例除了幾個參數外基本上都是相同的,有時就能夠大幅度的減少需要實例化類的數量。如果能把那些參數移到類實例的外面,在方法調用時將它們傳進來,就可以通過共享大幅度地減少單個實例的數目。也就是說,享元模式Flyweight執行時所需要的狀態有內部的也有外部的,內部狀態存儲於ConcreteFlyweight對象之中,而外部對象則應該考慮由客戶端對象存儲或計算,當調用Flyweight對象的操作時,將該狀態傳遞給它。

應用場景

如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時就應該考慮使用;還有就是對象的大多數狀態可以外部狀態,如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代很多組對象,此時可以考慮使用享元模式。

        java的String就是采用了這種方式。


package com.zcr.flyweight2;

public class User
{
    private String name;
   
    public User(String name)
    {
        this.name = name;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }
   
   
}

 

 

 

package com.zcr.flyweight2;

//享元設計模式實現

//網站抽象類
public abstract class WebSite
{
    //“使用”方法需要傳遞“用戶”對象
    public abstract void Use(User user);
}

 

 

 

 

 

package com.zcr.flyweight2;

//具體的網站類
public class ConcreteWebSite extends WebSite
{
    private String name = "";
   
    public ConcreteWebSite(String name)
    {
        this.name = name;
    }
   
    @Override
    public void Use(User user)
    {
        System.out.println("網站分類:"+name+"用戶名:"+user.getName());

    }

}

 

 

 

 

package com.zcr.flyweight2;

import java.util.Hashtable;

//網站工廠
public class WebsiteFactory
{
    private Hashtable<String,WebSite> flyweights = new Hashtable<String, WebSite>();
   
    //獲得網站分類
    public WebSite GetWebSiteCategory(String key)
    {
        //判斷是否存在這個對象,如果存在則直接返回,若不存在,則實例化它再返回
        if(!flyweights.contains(key))
        {
            flyweights.put(key, new ConcreteWebSite(key));
        }
        return flyweights.get(key);
    }
   
    //獲取網站分類的總數
    public int GetWebSiteCount()
    {
        return flyweights.size();
    }
}

 

 

 

 

package com.zcr.flyweight2;

public class FlyweightTest
{
    public static void main(String[] args)
    {
        WebsiteFactory f = new WebsiteFactory();
       
        WebSite fx = f.GetWebSiteCategory("產品展示");
        fx.Use(new User("小菜"));
       
        WebSite fy = f.GetWebSiteCategory("產品展示");
        fy.Use(new User("大煙籠"));
       
        WebSite fz = f.GetWebSiteCategory("產品展示");
        fz.Use(new User("大菜"));
       
        WebSite fl = f.GetWebSiteCategory("博客");
        fl.Use(new User("老頑童"));
       
        WebSite fm = f.GetWebSiteCategory("博客");
        fm.Use(new User("肥菜"));
       
        WebSite fn = f.GetWebSiteCategory("博客");
        fn.Use(new User("小小斌"));
       
        System.out.println("網站分類總數為:" + f.GetWebSiteCount());
    }
}

結果:

Copyright © Linux教程網 All Rights Reserved