博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

设计模式——享元模式(Flyweight)

Posted on 2008-08-29 14:11  Anna Yang  阅读(437)  评论(1编辑  收藏  举报
设计模式(12): 享元模式(Flyweight)
 
享元模式(Flyweight)
 
定义
     运用共享技术有效地支持大量细粒度的对象。
 
概述   
    面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面向对象的方式进行操作?
      
享元模式(Flyweight)
 
 
 Flyweight类,它是所有享元类的超类或接口,通过这个接口,Flyweight可以接受并作用于外部状态。
abstract class Flyweight
{
    
public abstract void Operation(int extrinsicstate);
}
 
ConcreteFlyweight是继承Flyweight超类或实现Flyweight接口。并为内部状态增加存储空间。
class ConcreteFlyweight:Flyweight
{
    
public override void Operation(int  extrinsicstate)
    {
        Console.WriteLine(
"具体Flyweight:" +extrinsicstate);
    }
}
 
UnsharedConcreteFlyweight是指那些不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但它并不强制共享。
class UnsharedConcreteFlyweight:Flyweight
{
    
public override void Operation(int  extrinsicstate)
    {
        Console.WriteLine(
"不共享的具体Flyweight:" +extrinsicstate);
    }
}
 
FlyweightFactory,是一个享元工厂,用来创建并管理Flyweight对象。它主要是用来确保合理地共享Flyweight,
当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)
 
class FlyweightFactory
{
    
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]);
    }
}
 
客户端代码:  
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);
    
    UnshareConcreteFlyweight uf
=new UnshareConcreteFlyweight();
    uf.Operation(
--extrinsicstate);
}
 
结果显示: 
具体extrinsicstate:21
具体extrinsicstate:
20
具体extrinsicstate:
19
不共享的具体extrinsicstate:
18
 
在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中 
key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对.
 
二.哈希表的简单操作
 在哈希表中添加一个key/value键值对:HashtableObject.Add(key,value);
在哈希表中去除某个key/value键值对:HashtableObject.Remove(key);
从哈希表中移除所有元素: HashtableObject.Clear();
判断哈希表是否包含特定键key: HashtableObject.Contains(key);
 
 在享元对象内部并且不会随环境改变而改变的共享部分,可以称为享元对象的内部状态,而随环境改变而改变的,不可以共享的状态就是外部状态了。
享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递过来,就可以通过共享大幅度地减少单个实例的数目。也就是说,享元模式Flyweight执行时所需要的状态是有内部的也可能有外部的,内部状态存储于 ConcreteFlyweight对象之中,而外部对象则应该考虑由客户端对象存储或计算,当调用Flyweight对象的操作时, 将该状态传递给它。
 
 
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)//实现“Use”方法
    {
        Console.WriteLine(
"网站分类:"+name+“用户:”+user.name);
    }
}

class WebSiteFatory
{
     
private Hashtable flyweights=new Hashtable();
     
public WebSite GetWebSiteCategory(string key)
     {
          
if(!flyweight.Containskey(key))
             flyweight.Add(key,
new ConcreteWebSite(name));
           
return ((WebSite)flyweights[key]);
     } 
    
public int GetWebSiteCount()
    {
        
return flyweight.count;
    }
}

    
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("泰特"));   
         Console.WriteLine(
"得到网站分类总数为{0}",f.GetWebSiteCount());    
    }
    
    显示结果
    网站分类:产品展示  用户:小明
    网站分类:产品展示  用户:晓阳
    网站分类:博客 用户:扬帆
    网站分类:博客 用户:泰特
    得到网站分类总数为 
2