今天我们将研究Flyweight 设计模式,Flyweight设计模式又被称为 享元设计模式 。
目录[ 隐藏 ]
根据GoF,flyweight设计模式意图是:
使用共享可以有效地支持大量细粒度对象
Flyweight设计模式是一种结构设计模式,如Facade模式,Adapter Pattern和Decorator模式。
当我们需要创建一个类的很多对象时,使用Flyweight设计模式。由于每个对象都占用对于低内存设备(例如移动设备或嵌入式系统)至关重要的内存空间,因此可以应用flyweight设计模式以通过共享对象来减少内存负载。
在我们应用flyweight设计模式之前,我们需要考虑以下因素:
要应用flyweight模式,我们需要将Object属性划分为内部属性和外部属性。内在属性使对象唯一,而外在属性由客户端代码设置并用于执行不同的操作。例如,对象圆可以具有外在属性,例如颜色和宽度。
为了应用flyweight模式,我们需要创建一个返回共享对象的Flyweight工厂。对于我们的示例,假设我们需要创建一个包含线条和椭圆的图形。因此,我们将有一个接口Shape
和它的具体实现为Line
和Oval
。Oval类将具有内在属性以确定是否使用给定颜色填充Oval,而Line将不具有任何内在属性。
Shape.java
package com.journaldev.design.flyweight;
import java.awt.Color;
import java.awt.Graphics;
public interface Shape {
public void draw(Graphics g, int x, int y, int width, int height,
Color color);
}
Line.java
package com.journaldev.design.flyweight;
import java.awt.Color;
import java.awt.Graphics;
public class Line implements Shape {
public Line(){
System.out.println("Creating Line object");
//adding time delay
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void draw(Graphics line, int x1, int y1, int x2, int y2,
Color color) {
line.setColor(color);
line.drawLine(x1, y1, x2, y2);
}
}
Oval.java
package com.journaldev.design.flyweight;
import java.awt.Color;
import java.awt.Graphics;
public class Oval implements Shape {
//intrinsic property
private boolean fill;
public Oval(boolean f){
this.fill=f;
System.out.println("Creating Oval object with fill="+f);
//adding time delay
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void draw(Graphics circle, int x, int y, int width, int height,
Color color) {
circle.setColor(color);
circle.drawOval(x, y, width, height);
if(fill){
circle.fillOval(x, y, width, height);
}
}
}
请注意,我有意在创建具体类的Object时引入了延迟,以表明flyweight模式可以用于实例化时需要花费大量时间的对象。
客户端程序将使用flyweight工厂来实例化Object,因此我们需要在工厂中保留一个客户端应用程序无法访问的Objects映射。
每当客户端程序调用获取Object的实例时,它应该从HashMap返回,如果没有找到,则创建一个新的Object并放入Map然后返回它。我们需要确保在创建Object时考虑所有内在属性。
我们的flyweight工厂类看起来像下面的代码。
ShapeFactory.java
package com.journaldev.design.flyweight;
import java.util.HashMap;
public class ShapeFactory {
private static final HashMap shapes = new HashMap();
public static Shape getShape(ShapeType type) {
Shape shapeImpl = shapes.get(type);
if (shapeImpl == null) {
if (type.equals(ShapeType.OVAL_FILL)) {
shapeImpl = new Oval(true);
} else if (type.equals(ShapeType.OVAL_NOFILL)) {
shapeImpl = new Oval(false);
} else if (type.equals(ShapeType.LINE)) {
shapeImpl = new Line();
}
shapes.put(type, shapeImpl);
}
return shapeImpl;
}
public static enum ShapeType{
OVAL_FILL,OVAL_NOFILL,LINE;
}
}
注意使用Java枚举用于类型安全,Java 组合物(形状地图)和 工厂模式 在 getShape
方法。
下面是一个使用flyweight模式实现的示例程序。
DrawingClient.java
package com.journaldev.design.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;
import com.journaldev.design.flyweight.ShapeFactory.ShapeType;
public class DrawingClient extends JFrame{
private static final long serialVersionUID = -1350200437285282550L;
private final int WIDTH;
private final int HEIGHT;
private static final ShapeType shapes[] = { ShapeType.LINE, ShapeType.OVAL_FILL,ShapeType.OVAL_NOFILL };
private static final Color colors[] = { Color.RED, Color.GREEN, Color.YELLOW };
public DrawingClient(int width, int height){
this.WIDTH=width;
this.HEIGHT=height;
Container contentPane = getContentPane();
JButton startButton = new JButton("Draw");
final JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
contentPane.add(startButton, BorderLayout.SOUTH);
setSize(WIDTH, HEIGHT);
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 < 20; ++i) {
Shape shape = ShapeFactory.getShape(getRandomShape());
shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),
getRandomHeight(), getRandomColor());
}
}
});
}
private ShapeType 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 / 10));
}
private int getRandomHeight() {
return (int) (Math.random() * (HEIGHT / 10));
}
private Color getRandomColor() {
return colors[(int) (Math.random() * colors.length)];
}
public static void main(String[] args) {
DrawingClient drawing = new DrawingClient(500,600);
}
}
我已经使用随机数生成在我们的框架中生成不同类型的形状。
如果您运行在客户端程序之上,您将注意到创建第一个Line对象和Oval对象的延迟,其中fill为true和false。之后,程序自使用共享对象以来快速执行。
多次单击“绘图”按钮后,框架看起来像下面的图像。
您将在命令行中看到以下输出,确认对象已共享。
Creating Line object
Creating Oval object with fill=true
Creating Oval object with fill=false
这就是所有的flyweight模式,我们将在未来的帖子中研究更多的设计模式。如果您喜欢它,请在评论部分分享您的想法并与其他人分享。
所有包装类 valueOf()
方法都使用缓存对象,显示使用Flyweight设计模式。最好的例子是Java String类String Pool实现。
这就是java中Flyweight设计模式的全部内容。
转载来源:https://www.journaldev.com/1562/flyweight-design-pattern-java