博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
享元模式(FlyWeight)
阅读量:5837 次
发布时间:2019-06-18

本文共 3094 字,大约阅读时间需要 10 分钟。

一、享元模式介绍

享元模式(FlyWeight):运用共享技术有效的支持大量细粒度对象的重用。

应用场景:如果项目中有很多完全相同或相似的对象,则可以使用享元模式,节省内存。

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

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

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

享元模式UML图

FlyweightFactory(享元工厂类):创建并管理享元对象,享元池一般设计成键值对

FlyWeight(抽象享元类):通常是一个接口或者抽象类,声明公共方法,这些方法可以向外界提供对象的内部状态,设置外部状态。

ConcreteFlyWeight(具体享元类):为内部状态提供成员变量进行存储

UnsharedConcreteFlyWeight(非共享享元类):不能被共享的子类可以设计为非共享享元类

例如:围棋中的享元模式,在围棋中,所有的白色或黑色的(形状、大小,颜色都一样)只是位置不同,那像这样的情况,可以使用享元模式。

把颜色、形状、大小给共享出来(内部状态)。位置不共享(外部状态)

 

二、享元模式代码实现

将棋子例子用代码实现

FlyWeight(抽象享元类):

1
2
3
4
5
6
7
8
9
10
11
/**
 
* 享元类接口:可以共享的有颜色,大小,形状
 
* FlyWeight(抽象享元类):通常是一个接口或者抽象类,声明公共方法,
 
* 这些方法可以向外界提供对象的内部状态,设置外部状态。
 
*/
public 
interface 
ChessFlyWeight {
    
//这里只设置一个颜色,大小和形状省略
    
void 
setColor(String c);
    
String getColor();
    
void 
display(Coordinate c);
//显示棋子
}

ConcreteFlyWeight(具体享元类):为内部状态提供成员变量进行存储

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//享元的具体实现:ConcreteFlyWeight(具体享元类):为内部状态提供成员变量进行存储
class 
concreteFlyWeight 
implements 
ChessFlyWeight{
    
private 
String color;
//这里就是为内部状态提供成员变量进行存储
    
//构造的时候初始化color属性
    
public 
concreteFlyWeight(String color) {
        
super
();
        
this
.color = color;
    
}
    
@Override
    
public 
void 
setColor(String c) {
        
this
.color = c;
    
}
    
@Override
    
public 
String getColor() {
        
return 
color;
    
}
    
@Override
    
public 
void 
display(Coordinate c) {
        
System.out.println(
"棋子颜色:"
+color);
        
System.out.println(
"棋子位置:("
+c.getX()+
","
+c.getY()+
")"
);
    
}
}

UnsharedConcreteFlyWeight(非共享享元类):不能被共享的子类可以设计为非共享享元类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 
* 坐标类(外部状态):棋子位置
 
* UnsharedConcreteFlyWeight(非共享享元类):不能被共享的子类可以设计为非共享享元类
 
*/
public 
class 
Coordinate {
    
private 
int 
x,y;
//坐标位置
    
public 
Coordinate(
int 
x, 
int 
y) {
        
super
();
        
this
.x = x;
        
this
.y = y;
    
}
    
public 
int 
getX() {
        
return 
x;
    
}
    
public 
void 
setX(
int 
x) {
        
this
.x = x;
    
}
    
public 
int 
getY() {
        
return 
y;
    
}
    
public 
void 
setY(
int 
y) {
        
this
.y = y;
    
}
}

定义一个FlyweightFactory(享元工厂类):

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 
* 享元工厂
 
* FlyweightFactory(享元工厂类):创建并管理享元对象,享元池一般设计成键值对
 
*/
public 
class 
ChessFlyWeightFactory {
    
//享元池:存放享元对象
    
private 
static 
Map<String,ChessFlyWeight> map = 
new 
HashMap<String,ChessFlyWeight>();
    
//提供一个享元工厂:创建和管理棋子
    
public 
static 
ChessFlyWeight getChess(String color){
        
if 
(map.get(color) != 
null 
) {
            
return 
map.get(color);
        
}
else
{
            
ChessFlyWeight chess = 
new 
concreteFlyWeight(color);
            
map.put(color, chess);
            
return 
chess;
        
}
    
}  
}

测试享元模式代码:

1
2
3
4
5
6
7
8
9
10
public 
static 
void 
main(String[] args) {
    
ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess(
"黑色"
);
//黑1
    
ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess(
"黑色"
);
//黑2
    
System.out.println(chess1==chess2);
//结果为true,相同或相似对象内存中只存在一份
      
    
//使用享元的外部状态
    
chess1.display(
new 
Coordinate(
10
10
));
//黑1在10,10的位置
    
chess2.display(
new 
Coordinate(
20
20
));
//黑2在20,20的位置
      
}

结果为:

                true

                棋子颜色:黑色

                棋子位置:(10,10)

                棋子颜色:黑色

                棋子位置:(20,20)

 

 

三、享元模式应用场景

享元模式开发中应用场景:

比如线程池,数据库连接池,这些都利用享元模式共享了部分属性,在池中操作。

String类的设计也是享元模式

优点:

1.极大的减少内存中对象的数量

2.相同或相似对象内存中只存在一份,极大的节约资源,提高系统性能

3.外部状态相对独立,不影响内部状态

缺点:

1.模式较复杂,使程序逻辑复杂化

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

 

 

参考资料:

  大话设计模式(带目录完整版).pdf

  HEAD_FIRST设计模式(中文版).pdf

  尚学堂_高淇_java300集最全视频教程_【GOF23设计模式】

 

转载地址:http://vujcx.baihongyu.com/

你可能感兴趣的文章
Mac 使用终端连接阿里云服务器
查看>>
LeetCode-4-Median of Two Sorted Arrays
查看>>
数据库原理学习
查看>>
scanf,fscanf,sscanf的区别
查看>>
SQL SERVER2005 复制订阅功能介绍
查看>>
staging server, source congtrol, deply workflow using git
查看>>
JAVA PERSISTENCE API (JPA)
查看>>
Spring中Bean的命名问题及ref和idref之间的区别
查看>>
如何安装一个优秀的BUG管理平台(转)
查看>>
<C Primer Pus>6 Using Relational Operators and Exprssions
查看>>
[HDU3507]Print Article
查看>>
linux socket网络编程 常用函数及头文件
查看>>
[android] 手机卫士关闭自动更新
查看>>
C# 委托和Lambda---基础
查看>>
大快网站:如何选择正确的hadoop版本
查看>>
Maven的使用笔记
查看>>
Python笔记
查看>>
JS全角与半角转化小结
查看>>
Winform读写App.config文件以及重启程序
查看>>
连上篇,编辑页
查看>>