设计模式(13) 享元模式(简单入门 结构模式)

来源:互联网 发布:unity3d 导出web 编辑:程序博客网 时间:2024/06/01 14:01

From Now On,Let us begin Design Patterns。

享元模式

定义

  • 采用一个共享来避免大量拥有相同内容对象的开销。这种开销中最常见、直观的就是内存的损耗。享元模式以共享的方式高效的支持大量的细粒度对象。 Use sharing to support large numbers of fine-grained objects efficiently.

(理解举例:享元模式在编辑器系统中大量使用。一个文编辑器往往会提供很多种字体,而通常的做法就是将每一个字母做成一个享元对象。享元对象的内蕴状态就是这个字母,而字母在文本中的位置和字体风格等其他信息则是外蕴状态。比如,字母a可以出现在文本的很多地方,虽然这些字母a的位置和字体风格不同,但是所有这些地方使用的都是同一个字母对象。这样一来,字母对象就可以在整个系统中共享。)
在名字和定义中都体现出了共享这一个核心概念,那么怎么来实现共享呢?要知道每个事物都是不同的,但是又有一定的共性,如果只有完全相同的事物才能共享,那么享元模式可以说就是不可行的;因此我们应该尽量将事物的共性共享,而又保留它的个性。为了做到这点,享元模式中区分了内蕴状态和外蕴状态。内蕴状态就是共性,外蕴状态就是个性了。

通用类图:
这里写图片描述

角色说明:
Flyweight——抽象享元角色:一个产品的抽象类,同时定义出对象的外部状态和内部状态的接口或实现。

ConcreteFlyweight——具体享元角色:实现抽象角色定义的业务。该角色中需要注意的是内部状态处理应该与环境无关,不应该出现一个操作改变了内部状态,同时修改了外部状态,这是不允许的。

UnsharedConcreteFlyweight——不可共享的享元角色:不存在外部状态或者安全要求(如线程安全)不能够使用共享技术的对象,该对象一般不会出现在享元工厂中。

FlyweightFactory——享元工厂:职责非常简单,就是构造一个池容器,同时提供从池中获得对象的方式

享元模式优点:

  • 大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能

  • 相同或相似的对象内存只保持一份,极大的节约资源,提高系统性能

  • 外部状态相对独立,不影响内部变化

享元模式的缺点:

  • 提高了系统的复杂性:需要分离出外部状态和内部状态

  • 为了节省内存,共享了内部状态,分离出了外部状态,而读取外部状态使运行时间变长。用时间换空间。

享元模式的使用场景:

内存属于稀缺资源,不能随意浪费。如果在一个系统中有很多个完全相同或相似的对象,我们就可以使用享元模式,让他们共享一份内存即可,不必每个都去实例化对象,从而节省内存空间。

细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份

需要缓冲池的场景

在java中,数据库连接池,线程池等即是用享元模式的应用

注意事项:


享元模式的例子:国际围棋

我摘录网上一个小伙伴写的围棋例子。
这里写图片描述

每一个围棋棋子都是一个对象,并都有如下属性:

颜色:可以共享的
位置:不可以共享的

围棋代码示例:

FlyWeight抽象享元类:
这里写图片描述

UnSharedConcreteFlyweight 非共享享元类:棋子坐标
这里写图片描述

ConcreteFlyWeight具体享元类:具体的围棋类
这里写图片描述

FlyWeightFactory享元工厂
这里写图片描述

场景和运行结果:
这里写图片描述

在Java语言中,String类型就是使用了享元模式。String对象是final类型,对象一旦创建就不可改变。在JAVA中字符串常量都是存在常量池中的,JAVA会确保一个字符串常量在常量池中只有一个拷贝。String a=”abc”,其中”abc”就是一个字符串常量。

享元对象能做到共享的关键是区分了内部状态和外部状态。

内部状态:可以共享,不会随环境改变而改变。
外部状态:不可以共享,会随环境改变而改变。

原创粉丝点击