当前位置: 首页 > news >正文

享元模式(Flyweight)解析例子

摘要:本文深入浅出的讲述了设计模式中的享元模式 , 并给出了简单的示例 , 例子浅显易懂 , 并附带源代码。
        享元 模式属于结构型模式,其意图是运用共享技术有效地支持大量细粒度的对象。有些应用程序得益于在其整个设计过程中采用面向对象技术,但是简单化的实现代价极大。flyweight是一个共享对象,它可以同时在多个场景中使用,并且每个场景中Flyweight队作为一个独立的对象,这一点与非共享对象的实例没有区别,Flyweight不能对他所运行的场景作出任何假设,这里的关键概念是内部状态和外部状态之间的区别。内部状态存储于Flyweight中,它包含了独立Flyweight场景的信息,这些信息使得Flyweight可以被共享,而外部状态取决于 Flyweight场景,并根据场景而变化,因此不可共享,用户对象负责在必要的时候将外部状态传递给FlyweightFlyweight模式对那些通常因为数量太大而难以用对象来表示的概念或者实体建立模型。
       适用性:Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它,当以下情况都成立时使用Flyweight模式。
l          一个应用程序使用了大量的对象,
l          完全有余使用了大量的对象,造成了很大的存储开销。
l          对象的大多数状态都可以变为外部状态。
l          如果删除对象的外部状态那么可以用相对较少的共享对象取代很多组对象。
l          应用程序不依赖于对象标识,由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。
1
 
参与者:       
       Flyweight: 描述一个接口,通过这个接口 flyweight 可以接受并作用于外部状态。
       ConcreteFlyweight(MyImage) :实现 flyweight 接口,并为内部状态增加存储空间。 ConcreteFlyweight 对象必须是可以共享的,它所存储的状态必须是内部的。即:它必须独立于 ConcreteFlyweight 对象的场景 .
UnsharedConcreteFlyweight: 并非所有的 Flyweight 子类都需要被共享。 Flyweight 接口使共享成为可能,但它并不强制共享,在 Flyweight 对象结构的某些层次, UnsharedConcreteFlyweight  对象通常将 ConcreteFlyweight 对象作为子节点。
FlyweightFactory(MyImageFactory) :创建并管理 Flyweight 对象。确保合理的共享 Flyweight 。当用户请求一个 flyweight 时, FlyweightFactory 对象提供一个已经创建的实例或者创建一个。
Client :维持一个对 Flyweight 的引用。计算或者存储一个(多个) flyweight 的外部状态。 Flyweight 执行时所需要的状态必定是内部的或者外部的状态,内部状态存储于 ConcreteFlyweight 对象中,而外部对象则由 Client 对象存储或计算,当用户调用 flyweight 对象的操作时,将该状态传递给他。用户不应直接对 ConcreteFlyweight 类进行实例化,而只能从 FlyweightFactory 对象得到 ConcreteFlyweight 对象,这可以保证对他们适当的进行共享。
本人认为 Flyweight 模式的核心就是把大量共享的对象收集在一起使用简单工厂模式进行管理,避免由于大量的小对象导致系统的内存过渡消耗。下面是一个简单的例子,例子不是很好,并不能显示 Flyweight 模式的所有特征。
客户端需要图片,从 MyImageFactory 中取得,如果 MyImageFactory 存储的 Image 中没有需要的图片 , 便创建一个,并把创建的图片存储在保留 Flyweight 的数组中,以便于下次直接获取。
相应的代码:
MyImage 的代码:
        package  flyweight;
import  java.awt.*;
import  java.awt.image.*;
import  java.io.*;
public   class  MyImage{
     private  Image  image ;
     public  MyImage(String file){
       Toolkit toolkit = Toolkit.getDefaultToolkit();  
       File f =  new  File(file);
        if (f.exists()){
            image  = toolkit.getImage(file);
       }
        else {
           System. out .println( "File unable to load!" );
       }
    }
     public   void  draw(Graphics g, int  x, int  y,String name,ImageObserver obs){
        g.drawImage( image ,x,y,30,30,obs);
        g.drawString(name,x,y+40);
    }
}
MyImageFactory 的代码:
package  flyweight;
public   class  MyImageFactory{
    MyImage[]  images ;
     public  MyImageFactory(){
        images  =  new  MyImage[3];
        for ( int  i=0;i<3;i++)
            images [i]=  new  MyImage( "flyweight/lili" +i+ ".gif" );
    }
     public  MyImage getMyImage( int  i){
        return   images [i];
    }
}
 
 
Client 代码:
package flyweight;
import javax.swing.*;
import java.awt.*;
public class Client extends JFrame{
       private MyImageFactory factory;
       private String[] names;
       public Client(){
              super("Flyweight sample");
              factory = new MyImageFactory();
              setSize(220,300);
              setVisible(true);
              repaint();
              names = new String[]{"pig","dog","cat"};
       }
       public void resize(){
              repaint();
       }
       public void paint(Graphics g){
              g.clearRect(0,0,getWidth(),getHeight());
              String name;
              for(int i=0;i<5;i++){
                     for(int j=0;j<5;j++){
                            int number=(int)(Math.random()*3%3);
                            MyImage myImage = factory.getMyImage(number);
                            number=(int)(Math.random()*3%3);
                            name = names[number];
                            myImage.draw(g,10+i*40,45+j*45,name,this);
                     }
              }
       }
       public static void main(String[] args){
              new Client();
       }
}
总结: Flyweight 的目标是尽量减少大量可以被共享的对象的数目,并把可变的与不可变得状态使用内部状态 (Flyweight) 与外部状态区分开来。
本文转自凌辉博客51CTO博客,原文链接http://blog.51cto.com/tianli/37118如需转载请自行联系原作者

lili00okok

相关文章:

  • msdb.dbo.suspect_pages
  • apache做反向代理服务器
  • 家庭调解员
  • XSS 攻击实验 防御方案
  • ORACLE 笔记
  • 浅析重定向与反弹Shell命令
  • JS设置Excel格式
  • Windows系统磁盘分区详解
  • 使用DELPHI编写一个小的控件
  • android Service控件
  • 当DiscuzNT遇上了Loadrunner(中)
  • Oracle数据字典
  • HDU_2196 Computer (树型dp)
  • 如何选购无线路由器
  • vs2005 vs2008中使用wince5.0 sdk 仿真器
  • [数据结构]链表的实现在PHP中
  • bootstrap创建登录注册页面
  • conda常用的命令
  •  D - 粉碎叛乱F - 其他起义
  • TCP拥塞控制
  • Yii源码解读-服务定位器(Service Locator)
  • zookeeper系列(七)实战分布式命名服务
  • 阿里云应用高可用服务公测发布
  • 大整数乘法-表格法
  • 类orAPI - 收藏集 - 掘金
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • 数据库巡检项
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • # .NET Framework中使用命名管道进行进程间通信
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • (1)(1.13) SiK无线电高级配置(五)
  • (11)MATLAB PCA+SVM 人脸识别
  • (23)Linux的软硬连接
  • (C语言)fread与fwrite详解
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (二)pulsar安装在独立的docker中,python测试
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (免费领源码)python#django#mysql校园校园宿舍管理系统84831-计算机毕业设计项目选题推荐
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)【Hibernate总结系列】使用举例
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .NET Remoting学习笔记(三)信道
  • .Net Web项目创建比较不错的参考文章
  • .NET 的静态构造函数是否线程安全?答案是肯定的!
  • .net 发送邮件
  • .NET 设计模式—简单工厂(Simple Factory Pattern)
  • .net6+aspose.words导出word并转pdf
  • .netcore 获取appsettings
  • [ Algorithm ] N次方算法 N Square 动态规划解决
  • [].shift.call( arguments ) 和 [].slice.call( arguments )
  • [ACTF2020 新生赛]Include