`

浅析轻量级设计模式

 
阅读更多

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

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实现

  1. package  com.javapapers.designpattern.flyweight;  
  2.    
  3. import  java.awt.Color;  
  4. import  java.awt.Graphics;  
  5.    
  6. public   interface  MyShape {  
  7.    public   void  draw(Graphics g,  int  x,  int  y,  int  width,  int  height,  
  8.       Color color,  boolean  fill, String font);  
  1. package  com.javapapers.designpattern.flyweight;   
  2. import  java.awt.Color;  
  3. import  java.awt.Font;  
  4. import  java.awt.Graphics;  
  5. public   class  MyOval  implements  MyShape {  
  6.    
  7.    private  String label;  
  8.    
  9.    public  MyOval(String label) {  
  10.      this .label = label;  
  11.    
  12.   }  
  13. public   void  draw(Graphics oval,  int  x,  int  y,  int  width,  int  height,  
  14.       Color color,  boolean  fill, String font) {  
  15.     oval.setColor(color);  
  16.     oval.drawOval(x, y, width, height);  
  17.     oval.setFont( new  Font(font,  12 12 ));  
  18.     oval.drawString(label, x + (width /  2 ), y);  
  19.      if  (fill)  
  20.       oval.fillOval(x, y, width, height);  
  21.   }  
  1. package  com.javapapers.designpattern.flyweight;  
  2.    
  3. import  java.awt.Color;  
  4. import  java.awt.Font;  
  5. import  java.awt.Graphics;  
  6.    
  7. public   class  MyRectangle  implements  MyShape {  
  8.    
  9.    private  String label;  
  10.    
  11.    public  MyRectangle(String label) {  
  12.      this .label = label;  
  13.    
  14.   }  
  15.    
  16.    public   void  draw(Graphics rectangle,  int  x,  int  y,  int  width,  int  height,  
  17.       Color color,  boolean  fill, String font) {  
  18.     rectangle.setColor(color);  
  19.     rectangle.drawRect(x, y, width, height);  
  20.     rectangle.setFont( new  Font(font,  12 12 ));  
  21.     rectangle.drawString(label, x + (width /  2 ), y);  
  22.      if  (fill)  
  23.       rectangle.fillRect(x, y, width, height);  
  24.   }  
  1. package  com.javapapers.designpattern.flyweight;  
  2.    
  3. import  java.util.HashMap;  
  4.    
  5. public   class  ShapeFactory {  
  6.    
  7.    private   static   final  HashMap shapes =  new  HashMap();  
  8.    
  9.    public   static  MyShape getShape(String label) {  
  10.     MyShape concreteShape = (MyShape) shapes.get(label);  
  11.    
  12.      if  (concreteShape ==  null ) {  
  13.        if  (label.equals( "R" )) {  
  14.         concreteShape =  new  MyRectangle(label);  
  15.       }  else   if  (label.equals( "O" )) {  
  16.         concreteShape =  new  MyOval(label);  
  17.       }  
  18.       shapes.put(label, concreteShape);  
  19.     }  
  20.      return  concreteShape;  
  21.   }  
  1. package  com.javapapers.designpattern.flyweight;  
  2.    
  3. import  java.awt.BorderLayout;  
  4. import  java.awt.Color;  
  5. import  java.awt.Container;  
  6. import  java.awt.Graphics;  
  7. import  java.awt.event.ActionEvent;  
  8. import  java.awt.event.ActionListener;  
  9.    
  10. import  javax.swing.JButton;  
  11. import  javax.swing.JFrame;  
  12. import  javax.swing.JPanel;  
  13.    
  14. public   class  Client  extends  JFrame {  
  15.    
  16.    private   static   final   int  WIDTH =  400 ;  
  17.    private   static   final   int  HEIGHT =  400 ;  
  18.    
  19.    private   static   final  String shapes[] = {  "R" "O"  };  
  20.    private   static   final  Color colors[] = { Color.red, Color.green, Color.blue };  
  21.    private   static   final   boolean  fill[] = {  true false  };  
  22.    private   static   final  String font[] = {  "Arial" "Courier"  };  
  23.    
  24.    public  Client() {  
  25.     Container contentPane = getContentPane();  
  26.    
  27.     JButton startButton =  new  JButton( "Draw Shapes" );  
  28.      final  JPanel panel =  new  JPanel();  
  29.    
  30.     contentPane.add(panel, BorderLayout.CENTER);  
  31.     contentPane.add(startButton, BorderLayout.SOUTH);  
  32.     setSize(WIDTH, WIDTH);  
  33.     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  34.     setVisible( true );  
  35.    
  36.     startButton.addActionListener( new  ActionListener() {  
  37.        public   void  actionPerformed(ActionEvent event) {  
  38.         Graphics g = panel.getGraphics();  
  39.          for  ( int  i =  0 ; i <  100 ; ++i) {  
  40.           MyShape shape = ShapeFactory.getShape(getRandomShape());  
  41.           shape.draw(g, getRandomX(), getRandomY(), getRandomWidth(),  
  42.               getRandomHeight(), getRandomColor(),  
  43.               getRandomFill(), getRandomFont());  
  44.         }  
  45.       }  
  46.     });  
  47.   }  
  48.    
  49.    private  String getRandomShape() {  
  50.      return  shapes[( int ) (Math.random() * shapes.length)];  
  51.   }  
  52.    
  53.    private   int  getRandomX() {  
  54.      return  ( int ) (Math.random() * WIDTH);  
  55.   }  
  56.    
  57.    private   int  getRandomY() {  
  58.      return  ( int ) (Math.random() * HEIGHT);  
  59.   }  
  60.    
  61.    private   int  getRandomWidth() {  
  62.      return  ( int ) (Math.random() * (WIDTH /  7 ));  
  63.   }  
  64.    
  65.    private   int  getRandomHeight() {  
  66.      return  ( int ) (Math.random() * (HEIGHT /  7 ));  
  67.   }  
  68.    
  69.    private  Color getRandomColor() {  
  70.      return  colors[( int ) (Math.random() * colors.length)];  
  71.   }  
  72.    
  73.    private   boolean  getRandomFill() {  
  74.      return  fill[( int ) (Math.random() * fill.length)];  
  75.   }  
  76.    
  77.    private  String getRandomFont() {  
  78.      return  font[( int ) (Math.random() * font.length)];  
  79.   }  
  80.    
  81.    public   static   void  main(String[] args) {  
  82.     Client client =  new  Client();  
  83.   }  
  84. }
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics