假设张三在接单平台接了很多单子,而且都是网站开发,但是形式是不同的,如博客形式、产品展示形式、论坛形式等,如果前期张三接了三个博客网站和三个产品展示网站的单子,那么他就要写博客和产品网站的代码,然后各实例化三份出来,这样就得到了三个博客网站及三个产品展示网站。那如果需要有100个博客或产品展示网站呢?张三还要继续实例化出100份代码吗?后期想要修改和维护得花费多大时间呀。换成是我们的话该怎么避免这个问题呢?
我们可以思考一下,虽然需要三个博客和三个产品展示,但是其功能是大体相似的,能不能让博客形式共享一份代码,产品展示共享一份代码,这样我们就将六个类变为两个类,而且维护和修改的成本大大降低。这就是接下来要说的享元模式的职责所在。
什么是享元模式?即是运用共享技术有效的支持大量细粒度的对象。结合上面的例子来说就是将博客形式的代码和产品展示的代码共享,不管多少个用户使用博客或产品展示,其使用的代码都是同一份博客代码或产品展示代码。
Talk is cheap. Show me the code!!!!
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 ConcreateWebsite : Website
{
private string name;
public ConcreateWebsite(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.Contains(key))
{
flyweights.Add(key, new ConcreateWebsite(key));
}
return (Website)flyweights[key];
}
public int GetWebsiteCount()
{
return flyweights.Count;
}
}
我们来解读这部分代码。首先我们创建了一个用户类User,其作用为模拟网站需要知道是哪个用户在使用;其次我们用一个抽象类Website将博客和产品展示的共同功能抽象出来;接着将具体的网站代码继承抽象类并实现其抽象方法Use,并且在构造函数中确定网站的类型;最后我们定义了一个网站工厂用来给外界提供某一类型的网站对象。
下面我们来看使用示例:
class Program
{
static void Main(string[] args)
{
WebsiteFactory factory = new WebsiteFactory();
Website zs = factory.GetWebsiteCategory("产品展示");
zs.Use(new User("张三"));
Website ls = factory.GetWebsiteCategory("产品展示");
ls.Use(new User("李四"));
Website ww = factory.GetWebsiteCategory("博客");
ww.Use(new User("王五"));
Console.ReadKey();
}
}
首先我们实例化了网站工厂类,用来提供不同的网站实例;接着我们从网站工厂中获取了一个叫产品展示的Website对象,最后调用使用网站的方法并将用户对象”张三“传入(下面两个同理)。其核心在于获取网站对象的方法中。通过该方法的实现过程可以发现,我们是根据网站类型进行划分的,也就是说这三个网站从头到尾实际上我们只保存了两个网站对象,分别为产品展示和博客,第二个获取的产品展示网站其实就是第一个产品展示网站的实例对象,唯一区分的只是用户的不同而已。这样做的好处就是哪怕我们需要成百上千个网站,只要它们的类型是一样的,那么它们使用的就是同一份代码,不需要实例化对应数量的对象,同时也降低了内存、CPU的占用,使得性能大大提升。
不可能所有类型的网站都可以抽象出共同的部分,如购物网站有购买链接而博客网站没有购买链接,这时候该怎么办呢?我们可将不需要共享的部分单独拎出来组成一个类,因为享元模式不强制所有类必须共享。这就是享元模式中的内部状态和外部状态的表现,其定义为:在享元对象内部并且不会随环境改变而改变的部分,就叫内部状态;反之需要随环境改变而改变的部分,就叫外部状态。
好了,以上就是享元模式的解读及使用示例。最后,thanks for reading!!!!
注:本人的设计模式系列是根据大话设计模式一书中的内容,加以自身总结说明,一方面想多锻炼自身的表达能力,另一方面希望能够提升自身的编程能力及代码架构水平。若是能让更多的人通过我的文章来明白该设计模式的作用、应用场景及独立设计出来,当然也是对我个人表达能力的提升及掌握程度的认可。最后再次说明,本文内容来自大话设计模式一书,我只是写出来并加以总结希望达到熟练掌握的程度。如果你通过本文搞懂了,那么50%归功于此书,49%归功于你自己,1%为本人(脸都不要了)。