浅析轻量级设计模式
2016-08-25 16:39
92 查看
轻量级设计模式是通过共享对象来减少内存负载,它通过把对象属性分离成内部和外部两种来实现对资源的共享。
GoF(Gang of Four)说:“运用共享技术高效的支持大量细粒度对象
”。轻量级模式的核心就是“共享
”。
何时使用轻量级设计模式,可以参照下面几个因素:
需要创建大量对象。
考虑内存成本。
大多数对象属性可以对外共享。
应用程序不必授权给唯一的对象,因为同一对象被实例后需要被重复使用。
外在状态可以被计算而不是存储,这样更好(下面解释)。
现在,一台电脑内存平均都有5O0GB硬盘和4GB
RAM,这是不是意味着我们不需要去考虑内存和成本了呢?由于成本下降让我们使用起来没有了限制,移动设备每天都在增加,而它们仍然存在内存约束。假设你
创建一个宇宙地图项目,你需要给每个星星创建对象,你想想,这个需要多少内存,GoF
在他们的书里给了一个例子。如果在每一个文件里面都需要为每个角色创建对象,想象一下文件将会多大,还何谈性能?
如何应用轻量级
在使用轻量级之前,应该先解析大对象类型,核心思路是通过重用
减少对象的创建。创建一小群能够通过分享重用的对象。细致分析每个对象属性,它们可以被分离成内在和外在两种。通过上下文来进行共享。让我们来看一个例子。
假设在一个文本编辑器中只能输入A到Z这26个字母,如果我们要使用这个编辑创建100页文档,我可能会有200000(2000*100)个字符
(假设2000字节/页)。如果没有轻量级,我们将会创建200000个对象去进行细粒度控制。每个字符也会有它们自己的属性,比如颜色、字体、尺寸等
等,这里我们该如何应用轻量级呢?
内部和外部状态
创建26个对象(从A到Z)映射每个单独的字符。这些26个字符将会有它们字节的内部状态特征,比如说对象‘a’将会有“a”字符的特征。那颜色、
字体、大小这些该怎么处理呢?这些外在状态将通过客户端代码创建。存储26个对象,通过客户端代码获得所需的字符/对象特征,并且通过外在状态进行上下联
系。关于上下文意味着,字符‘a’在第一行可能是红色而在其他行可能是蓝色。
实现轻量级
对象的内部状态被称为轻量级对象。当实现轻量级时,我们将会创建一些具体的对象并且会存储一些内在特征。我们将会有一个工厂去创建这些具体对象,而这个工厂就称作轻量级工厂
。这个工厂的作用是保证这些对象可以进行共享并且不会被重复创建。
让我们来看一个例子吧。我们要画多种不同的几何图形,比如矩形、椭圆形,每个图形可能会使用不同的颜色,尺寸,填充类型,字体。为了方便实现,我们将图形限制成矩形和椭圆形两种,每个图形都会有一个标签与它们的形状相映射。矩形标签为“R”,椭圆形标签为“O”。
使用内部状态作为唯一的标签。因此我们将会有两个轻量级对象。颜色、尺寸、填充类型、字体这些作为外部状态。我们将会使用一个轻量级工厂来维护这两个对象,并且会把它们相应地的分发到客户端。这里有一个接口用来实现轻量级并且会有相同的设计图。
为了使用方便,客户端代码将使用random产生器来创建外在属性。我们将会动态计算和使用这些不被存储的外在属性。
轻量级模式的UML图
![](http://articles.csdn.net/uploads/allimg/120625/1509441554-0.png)
轻量级模式的Java实现
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Graphics;
public
interface
MyShape {
public
void
draw(Graphics g,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font);
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Font;
import
java.awt.Graphics;
public
class
MyOval
implements
MyShape {
private
String label;
public
MyOval(String label) {
this
.label = label;
}
public
void
draw(Graphics oval,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font) {
oval.setColor(color);
oval.drawOval(x, y, width, height);
oval.setFont(
new
Font(font,
12
,
12
));
oval.drawString(label, x + (width /
2
), y);
if
(fill)
oval.fillOval(x, y, width, height);
}
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Font;
import
java.awt.Graphics;
public
class
MyRectangle
implements
MyShape {
private
String label;
public
MyRectangle(String label) {
this
.label = label;
}
public
void
draw(Graphics rectangle,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font) {
rectangle.setColor(color);
rectangle.drawRect(x, y, width, height);
rectangle.setFont(
new
Font(font,
12
,
12
));
rectangle.drawString(label, x + (width /
2
), y);
if
(fill)
rectangle.fillRect(x, y, width, height);
}
}
package
com.javapapers.designpattern.flyweight;
import
java.util.HashMap;
public
class
ShapeFactory {
private
static
final
HashMap shapes =
new
HashMap();
public
static
MyShape getShape(String label) {
MyShape concreteShape = (MyShape) shapes.get(label);
if
(concreteShape ==
null
) {
if
(label.equals(
"R"
)) {
concreteShape =
new
MyRectangle(label);
}
else
if
(label.equals(
"O"
)) {
concreteShape =
new
MyOval(label);
}
shapes.put(label, concreteShape);
}
return
concreteShape;
}
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.BorderLayout;
import
java.awt.Color;
import
java.awt.Container;
import
java.awt.Graphics;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
javax.swing.JButton;
import
javax.swing.JFrame;
import
javax.swing.JPanel;
public
class
Client
extends
JFrame {
private
static
final
int
WIDTH =
400
;
private
static
final
int
HEIGHT =
400
;
private
static
final
String shapes[] = {
"R"
,
"O"
};
private
static
final
Color colors[] = { Color.red, Color.green, Color.blue };
private
static
final
boolean
fill[] = {
true
,
false
};
private
static
final
String font[] = {
"Arial"
,
"Courier"
};
public
Client() {
Container contentPane = getContentPane();
JButton startButton =
new
JButton(
"Draw Shapes"
);
final
JPanel panel =
new
JPanel();
contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(startButton, BorderLayout.SOUTH);
setSize(WIDTH, WIDTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(
true
);
startButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent event) {
Graphics g = panel.getGraphics();
for
(
int
i =
0
; i <
100
; ++i) {
MyShape shape = ShapeFactory.getShape(getRandomShape());
shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
getRandomHeight(), getRandomColor(),
getRandomFill(), getRandomFont());
}
}
});
}
private
String getRandomShape() {
return
shapes[(
int
) (Math.random() * shapes.length)];
}
private
int
getRandomX() {
return
(
int
) (Math.random() * WIDTH);
}
private
int
getRandomY() {
return
(
int
) (Math.random() * HEIGHT);
}
private
int
getRandomWidth() {
return
(
int
) (Math.random() * (WIDTH /
7
));
}
private
int
getRandomHeight() {
return
(
int
) (Math.random() * (HEIGHT /
7
));
}
private
Color getRandomColor() {
return
colors[(
int
) (Math.random() * colors.length)];
}
private
boolean
getRandomFill() {
return
fill[(
int
) (Math.random() * fill.length)];
}
private
String getRandomFont() {
return
font[(
int
) (Math.random() * font.length)];
}
public
static
void
main(String[] args) {
Client client =
new
Client();
}
}
Flyweight.zip (9.5 KB)
下载次数: 1
GoF(Gang of Four)说:“运用共享技术高效的支持大量细粒度对象
”。轻量级模式的核心就是“共享
”。
何时使用轻量级设计模式,可以参照下面几个因素:
需要创建大量对象。
考虑内存成本。
大多数对象属性可以对外共享。
应用程序不必授权给唯一的对象,因为同一对象被实例后需要被重复使用。
外在状态可以被计算而不是存储,这样更好(下面解释)。
现在,一台电脑内存平均都有5O0GB硬盘和4GB
RAM,这是不是意味着我们不需要去考虑内存和成本了呢?由于成本下降让我们使用起来没有了限制,移动设备每天都在增加,而它们仍然存在内存约束。假设你
创建一个宇宙地图项目,你需要给每个星星创建对象,你想想,这个需要多少内存,GoF
在他们的书里给了一个例子。如果在每一个文件里面都需要为每个角色创建对象,想象一下文件将会多大,还何谈性能?
如何应用轻量级
在使用轻量级之前,应该先解析大对象类型,核心思路是通过重用
减少对象的创建。创建一小群能够通过分享重用的对象。细致分析每个对象属性,它们可以被分离成内在和外在两种。通过上下文来进行共享。让我们来看一个例子。
假设在一个文本编辑器中只能输入A到Z这26个字母,如果我们要使用这个编辑创建100页文档,我可能会有200000(2000*100)个字符
(假设2000字节/页)。如果没有轻量级,我们将会创建200000个对象去进行细粒度控制。每个字符也会有它们自己的属性,比如颜色、字体、尺寸等
等,这里我们该如何应用轻量级呢?
内部和外部状态
创建26个对象(从A到Z)映射每个单独的字符。这些26个字符将会有它们字节的内部状态特征,比如说对象‘a’将会有“a”字符的特征。那颜色、
字体、大小这些该怎么处理呢?这些外在状态将通过客户端代码创建。存储26个对象,通过客户端代码获得所需的字符/对象特征,并且通过外在状态进行上下联
系。关于上下文意味着,字符‘a’在第一行可能是红色而在其他行可能是蓝色。
实现轻量级
对象的内部状态被称为轻量级对象。当实现轻量级时,我们将会创建一些具体的对象并且会存储一些内在特征。我们将会有一个工厂去创建这些具体对象,而这个工厂就称作轻量级工厂
。这个工厂的作用是保证这些对象可以进行共享并且不会被重复创建。
让我们来看一个例子吧。我们要画多种不同的几何图形,比如矩形、椭圆形,每个图形可能会使用不同的颜色,尺寸,填充类型,字体。为了方便实现,我们将图形限制成矩形和椭圆形两种,每个图形都会有一个标签与它们的形状相映射。矩形标签为“R”,椭圆形标签为“O”。
使用内部状态作为唯一的标签。因此我们将会有两个轻量级对象。颜色、尺寸、填充类型、字体这些作为外部状态。我们将会使用一个轻量级工厂来维护这两个对象,并且会把它们相应地的分发到客户端。这里有一个接口用来实现轻量级并且会有相同的设计图。
为了使用方便,客户端代码将使用random产生器来创建外在属性。我们将会动态计算和使用这些不被存储的外在属性。
轻量级模式的UML图
![](http://articles.csdn.net/uploads/allimg/120625/1509441554-0.png)
轻量级模式的Java实现
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Graphics;
public
interface
MyShape {
public
void
draw(Graphics g,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font);
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Font;
import
java.awt.Graphics;
public
class
MyOval
implements
MyShape {
private
String label;
public
MyOval(String label) {
this
.label = label;
}
public
void
draw(Graphics oval,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font) {
oval.setColor(color);
oval.drawOval(x, y, width, height);
oval.setFont(
new
Font(font,
12
,
12
));
oval.drawString(label, x + (width /
2
), y);
if
(fill)
oval.fillOval(x, y, width, height);
}
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.Color;
import
java.awt.Font;
import
java.awt.Graphics;
public
class
MyRectangle
implements
MyShape {
private
String label;
public
MyRectangle(String label) {
this
.label = label;
}
public
void
draw(Graphics rectangle,
int
x,
int
y,
int
width,
int
height,
Color color,
boolean
fill, String font) {
rectangle.setColor(color);
rectangle.drawRect(x, y, width, height);
rectangle.setFont(
new
Font(font,
12
,
12
));
rectangle.drawString(label, x + (width /
2
), y);
if
(fill)
rectangle.fillRect(x, y, width, height);
}
}
package
com.javapapers.designpattern.flyweight;
import
java.util.HashMap;
public
class
ShapeFactory {
private
static
final
HashMap shapes =
new
HashMap();
public
static
MyShape getShape(String label) {
MyShape concreteShape = (MyShape) shapes.get(label);
if
(concreteShape ==
null
) {
if
(label.equals(
"R"
)) {
concreteShape =
new
MyRectangle(label);
}
else
if
(label.equals(
"O"
)) {
concreteShape =
new
MyOval(label);
}
shapes.put(label, concreteShape);
}
return
concreteShape;
}
}
package
com.javapapers.designpattern.flyweight;
import
java.awt.BorderLayout;
import
java.awt.Color;
import
java.awt.Container;
import
java.awt.Graphics;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
javax.swing.JButton;
import
javax.swing.JFrame;
import
javax.swing.JPanel;
public
class
Client
extends
JFrame {
private
static
final
int
WIDTH =
400
;
private
static
final
int
HEIGHT =
400
;
private
static
final
String shapes[] = {
"R"
,
"O"
};
private
static
final
Color colors[] = { Color.red, Color.green, Color.blue };
private
static
final
boolean
fill[] = {
true
,
false
};
private
static
final
String font[] = {
"Arial"
,
"Courier"
};
public
Client() {
Container contentPane = getContentPane();
JButton startButton =
new
JButton(
"Draw Shapes"
);
final
JPanel panel =
new
JPanel();
contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(startButton, BorderLayout.SOUTH);
setSize(WIDTH, WIDTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(
true
);
startButton.addActionListener(
new
ActionListener() {
public
void
actionPerformed(ActionEvent event) {
Graphics g = panel.getGraphics();
for
(
int
i =
0
; i <
100
; ++i) {
MyShape shape = ShapeFactory.getShape(getRandomShape());
shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
getRandomHeight(), getRandomColor(),
getRandomFill(), getRandomFont());
}
}
});
}
private
String getRandomShape() {
return
shapes[(
int
) (Math.random() * shapes.length)];
}
private
int
getRandomX() {
return
(
int
) (Math.random() * WIDTH);
}
private
int
getRandomY() {
return
(
int
) (Math.random() * HEIGHT);
}
private
int
getRandomWidth() {
return
(
int
) (Math.random() * (WIDTH /
7
));
}
private
int
getRandomHeight() {
return
(
int
) (Math.random() * (HEIGHT /
7
));
}
private
Color getRandomColor() {
return
colors[(
int
) (Math.random() * colors.length)];
}
private
boolean
getRandomFill() {
return
fill[(
int
) (Math.random() * fill.length)];
}
private
String getRandomFont() {
return
font[(
int
) (Math.random() * font.length)];
}
public
static
void
main(String[] args) {
Client client =
new
Client();
}
}
Flyweight.zip (9.5 KB)
下载次数: 1
相关文章推荐
- IOS设计模式浅析之原型模式(Prototype)
- IOS设计模式浅析之工厂方法模式(Factory Method)
- IOS设计模式浅析之简单工厂模式(SimpleFactory)
- 浅析设计模式之抽象工厂模式
- IOS设计模式浅析之单例模式(Singleton)
- IOS设计模式浅析之工厂方法模式(Factory Method)
- java基础――浅析设计模式之单例模式
- 设计模式浅析
- 浅析设计模式系列之一 ——综述
- IOS设计模式浅析之建造者模式(Builder)
- 浅析设计模式之模板方法
- 十四.结构型设计模式——Flyweight Pattern(轻量级模式)
- 浅析设计模式之FactoryMethod
- 浅析jQuery核心架构中应用Closure的设计模式
- 浅析设计模式之单件模式
- 浅析设计模式之策略模式--为什么总是继承?
- 极速理解设计模式系列:14.轻量级模式(Flyweight Pattern)
- IOS设计模式浅析之原型模式(Prototype)
- IOS设计模式浅析之建造者模式(Builder)
- 设计模式浅析之Singleton