求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
浅析轻量级设计模式
 

作者:张红月 ,发布于2012-9-21,来源:CSDN编译

 

轻量级设计模式是通过共享对象来减少内存负载,它通过把对象属性分离成内部和外部两种来实现对资源的共享。

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图

轻量级模式的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();
   }
} 

点击下载源码

上面代码输出效果图


相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践
 
分享到
 
 
     


重构-使代码更简洁优美
Visitor Parttern
由表及里看模式
设计模式随笔系列
深入浅出设计模式-介绍
.NET中的设计模式
更多...   

相关培训课程

J2EE设计模式和性能调优
应用模式设计Java企业级应用
设计模式原理与应用
J2EE设计模式指南
单元测试+重构+设计模式
设计模式及其CSharp实现


某电力公司 设计模式原理
蓝拓扑 设计模式原理及应用
卫星导航 UML & OOAD
汤森路透研发中心 UML& OOAD
中达电通 设计模式原理
西门子 嵌入式设计模式
更多...