面向对象的思想很好地解决了抽象性的问题,一般也不会出现性能上的问题。但是在某些情况下,对象的数量可能会太多,从而导致了运行时的代价。那么我们如何去避免大量细粒度的对象,同时又不影响客户程序使用面向对象的方式进行操作?
享元模式:运用共享技术有效的支持大量细粒度的对象
结构图:
解释:
- FlyweightFactory:一个享元工厂,用来创建并管理Flyweight对象,它主要是用来确保合理的共享Flyweight,当用户请求一个Flyweight时,FlyweightFactory对象提供一个已创建的实例或者创建一个(如果不存在的话)
- Flyweight:所有具体享元类的超类或接口,通过这个接口,Flyweight尅接受并作用于外部状态
- ConcreteFlyweight:继承Flyweight超累或实现Flyweight接口,并为内部状态增加储存空间
- UnsharedConcreteFlyweight:指那些不需要共享的Flyweight子类,因为Flyweight接口共享成为可能,但它并不强制共享
代码实现:
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
{
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]);
}
}
}
例子:网站共享
结构图:
代码实现:
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 ;
}
}
}
运行结果:
享元模式的应用
- 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时
- 当对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代多组对象
享元模式的优点:
- 实例总数少了
- 共享的对象越多,存储节约也就越多,节约量随着共享状态的增多而增大