享元模式C++实现(flyweight)

简介

动机

  • 假设成立一个外包公司,主要给一些私营业主建网站。
  • 商家客户都类似,要求也就是信息发布、产品展示、博客留言、论坛等功能。
  • 各个客户要求差别不大,但客户数量多。

内部状态和外部状态

  • 在享元对象内部并且不会随环境改变而改变的共享部分,可以成为是享元对象的内部状态。
  • 随环境改变而改变的、不可以共享的状态就是外部状态。
  • 享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据,如果能发现这些实例除了几个参数外基本都是相同的,有时就能大幅度减少需要实例化的类的数量。
  • 如果能把那些参数移到类实例外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

适用性

  • 当以下情况成立时使用享元模式:
    • 一个应用程序使用大量的对象,并且完全是由于使用大量的对象,造成很大的存储开销。
    • 对象的大多数状态都可变为外部状态,并且如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
    • 应用程序不依赖于对象表示。由于Flyweight对象可以被共享,对于概念上明显有别的对象,表示测试将返回真值。

结构

参与者

  • Flyweight
    • 描述一个接口,通过这个接口Flyweight可以接受并作用于外部状态。
  • ConcreteFlyweight
    • 实现Flyweight接口,并为内部状态增加空间。ConcreteFlyweight对象必须是可共享的。它所存储状态必须是内部的;即,它必须独立于ConcreteFlyweight的场景。
  • UnsharedConcreteFlyweight
    • 并非所有的Flyweight子类都需要被共享。 Flyweight接口使共享成为可能,但它并不强制共享。
  • FlyweightFactory
    • 创建并管理flyweight对象。
    • 确保合理地共享flyweight。当用户请求一个flyweight时,Flyweight对象提供一个已创建的实例或者创建一个(如果不存在的话)。
  • Client
    • 维持一个对flyweight的引用。
    • 计算或存储一个(多个)flyweight的外部状态。

协作

  • Flyweight执行时所需状态必定是内部的或外部的。内部状态存储于ConcreteFlyweight对象之中;而外部对象则由Client对象存储或计算。当用户调用flyweight对象的操作时,将该状态传递给它。
  • 用户不直接对ConcreteFlyweight类进行实例化,而只能从FlyweightFactory对象得到ConcreteFlyweight对象,这可以保证对它们适当地进行共享。

实例

假设成立一个外包公司,主要给一些私营业主建网站。商家客户要求的功能包括信息发布、产品展示、博客留言等功能。

共有a-j 10个客户,其中a-c客户需要信息发布,d-f需要产品展示,g-j客户需要博客功能。

利用享元模式模拟该公司建立网站,输出如下:

客户a: 信息发布

客户b:信息发布

。。。

网站分类总数为:3

UML

代码

在本次实验中:客户的号码就是外部状态,应该由专门的对象来处理,在这里简化为char类型的id

另外注意没有UnsharedConcreteFlyweight

 

Website类即Flyweight

ConcreteWebsite类即ConcreteFlyweight

 

结果

总结

①本次实验掌握了享元模式的原理与方法,在选择flyweight时,要注意选择合适的享元类。

②按照实际情况分情况讨论具体的Flyweight类。

③不管建几个网站,只要是‘产品展示’,都是一样的,只要是‘博客’,也是完全相同的,但这样是有问题的,给企业建的网站不是一家企业,它们的数据不会相同,所以至少它们都应该有不同的账号(id值)。实际上这样写没有体现对象间的不同,只体现了它们共享的部分。

 

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注