面向對象的思想很好地解決了抽象性的問題,一般也不會出現性能上的問題。但是在某些情況下,對象的數量可能會太多,從而導致了運行時的代價。那麼我們如何去避免大量細粒度的對象,同時又不影響客戶程序使用面向對象的方式進行操作?
享元模式:運用共享技術有效的支持大量細粒度的對象
結構圖:
解釋:
FlyweightFactory:一個享元工廠,用來創建並管理Flyweight對象,它主要是用來確保合理的共享Flyweight,當用戶請求一個Flyweight時,FlyweightFactory對象提供一個已創建的實例或者創建一個(如果不存在的話)
Flyweight:所有具體享元類的超類或接口,通過這個接口,Flyweight尅接受並作用於外部狀態
ConcreteFlyweight:繼承Flyweight超累或實現Flyweight接口,並為內部狀態增加儲存空間
UnsharedConcreteFlyweight:指那些不需要共享的Flyweight子類,因為Flyweight接口共享成為可能,但它並不強制共享
代碼實現:
[html]
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace 享元模式
{
class Program
{
static void Main(string[] args)
{
//代碼外部狀態
int extrinsicstate = 22;
FlyweightFactory f = new FlyweightFactory();
Flyweight fx = f.GetFlyweight("X");
fx.Operation(--extrinsicstate);
Flyweight fy = f.GetFlyweight("Y");
fy.Operation(--extrinsicstate);
Flyweight fz = f.GetFlyweight("Z");
fz.Operation(--extrinsicstate);
Flyweight uf = new UnsharedConcreteFlyweight();
uf.Operation(--extrinsicstate);
Console.Read();
}
}
//Flyweight 類,它是所有具體享元類的超類或接口
abstract class Flyweight
{
public abstract void Operation(int extrinsicstate);
}
//ConcreteFlyweight類,繼承Flyweight超類或實現Flyweight接口,並為內部狀態增加存儲空間
class ConcreteFlyweight : Flyweight
{ www.2cto.com
public override void Operation(int extrinstate)
{
Console.WriteLine("具體Flyweight:" + extrinstate);
}
}
//UnsharedConcreteFlyweight類,代表那些不需要共享的Flyweight子類
class UnsharedConcreteFlyweight : Flyweight
{
public override void Operation(int extrinsicstate)
{
Console.WriteLine("不共享的具體Flyweight:" + extrinsicstate);
}
}
//FlyweightFactory類,是一個享元工廠,用來創建並管理Flyweight對象
class FlyweightFactory
{
//使用Hashtable需要調用using System.Collections;
private Hashtable flyweights = new Hashtable();
public FlyweightFactory()
{
flyweights.Add("X", new ConcreteFlyweight());
flyweights.Add("Y", new ConcreteFlyweight());
flyweights.Add("Z", new ConcreteFlyweight());
}
public Flyweight GetFlyweight(string key)
{
return ((Flyweight)flyweights[key]);
}
}
}
</span>
例子:網站共享
結構圖:
代碼實現:
[html]
<span style="font-size:18px;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace 網站共享代碼
{
class Program
{
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("唐歡"));
Console .WriteLine ("得到網站分類總數為{0}",f.GetWebSiteCount ());
Console.Read();
}
}
//用戶類 ,用於網站的客戶賬號,是“網站”類的外部狀態
public class User
{
private string name;
public User(string name)
{
this.name = name;
}
public string Name
{
get { return name; }
}
}
//網站抽象類
abstract class WebSite
{
public abstract void Use(User user);
}
//具體網站類
class ConcreteWebSite : WebSite
{
private string name = "";
public ConcreteWebSite(string name)
{
this.name = name;
}
public override void Use(User user)
{
Console.WriteLine("網站分類:" + name + "用戶:" + user.Name);
}
}
//網站工廠類
class WebSiteFactory
{
private Hashtable flyweights=new Hashtable ();
//獲得網站分類
public WebSite GetWebSiteCategory(string key)
{
if (!flyweights .ContainsKey (key ))
flyweights .Add (key ,new ConcreteWebSite (key ));
return ((WebSite )flyweights [key ]);
}
//獲得網站分類總數
public int GetWebSiteCount()
{
return flyweights .Count ;
}
}
}
</span>
運行結果:
享元模式的應用
如果一個應用程序使用了大量的對象,而大量的這些對象造成了很大的存儲開銷時
當對象的大多數狀態可以外部狀態,如果刪除對象的外部狀態,那麼可以用相對較少的共享對象取代多組對象
享元模式的優點:
實例總數少了
共享的對象越多,存儲節約也就越多,節約量隨著共享狀態的增多而增大