zoukankan      html  css  js  c++  java
  • 享元模式


    享元模式

    • 享元模式:是一种重要的池技术的实现方式,使用共享对象可有效地支持大量的细粒度的对象。
    • 享元模式的定义提出了两个要求:细粒度的对象和共享对象,分配太多的对象到应用程序当中去将有损程序的性能,而且还容易造成内存溢出,通过享元模式的共享对象的技术来解决这些问题。首先我们先了解一下对象的内部状态(intrinsic)和外部状态(extrinsic)。
      • 内部状态:对象可共享出来的信息,存储在享元对象的内部并且不会随环境改变而改变,作为一个对象的动态附加信息,不必直接存储在具体某个对象中。
      • 外部状态:对象得以依赖的一个标记,随环境的改变而改变、不可共享的状态,是一批对象的统一标识,是唯一的一个索引值。
    • 有了对象的两种状态,我们来看一下享元模式的通用类图:

    public abstract class Flyweight {
        //内部状态
        private String intrinsic;
        //外部状态
        protected final String extrinsic;
        public Flyweight(String extrinsic){
            this.extrinsic = extrinsic;
        }
        public abstract void operate();
        public String getIntrinsic(){
            return this.intrinsic;
        }
        public void setIntrinsic(String intrinsic){
            this.intrinsic = intrinsic;
        }
    }
    
    public class ConcreteFlyweight1 extends Flyweight{
    
        public ConcreteFlyweight1(String extrinsic) {
            super(extrinsic);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void operate() {
            // TODO Auto-generated method stub
            
        }
    }
    
    public class FlyweightFactory {
        private static HashMap<String, Flyweight> flyWeights = new HashMap<String, Flyweight>();
        public static Flyweight getFlyweight(String key){
            Flyweight flyweight = null;
            if(flyWeights.containsKey(key)){
                flyweight = flyWeights.get(key);
            }else{
                //根据外部状态创建享元对象
                flyweight = new ConcreteFlyweight1(key);
                //将享元对象放到池中
                flyWeights.put(key, flyweight);
            }
            return flyweight;
        }
    }
    View Code
    享元模式的优缺点

        享元模式是一个非常简单的模式,它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但同时也提高了系统的复杂性,需要分离出外部状态和内部状态,而外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统逻辑混乱。

    享元模式的使用场景
    • 系统中存在大量的相似对象;
    • 细粒度的对象具备较近的外部状态,而且内部状态与环境无关,也就是说对象没有特定身份;
    • 需要缓冲池的场景。
    享元模式的扩展
    • 线程安全问题,当多个线程同时从对象缓冲池中取对象,并对对象的内部状态进行修改时,可能会造成线程的不安全。
    public class MultiThread extends Thread{
        private Flyweight flyweight;
        private String intrinsic;
        public MultiThread(Flyweight flyweight){
            this.flyweight = flyweight;
            this.intrinsic = flyweight.getIntrinsic();
        }
        public void run(){
            String intrinsic = flyweight.getIntrinsic();
            if(!intrinsic.equalsIgnoreCase(this.intrinsic)){
                System.out.print("线程不安全......");
                System.out.println(this.intrinsic + "     " + intrinsic);
            }
        }
    }
    
    public class Client {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Flyweight flyweight = FlyweightFactory.getFlyweight("123");
            while(true){
                flyweight.setIntrinsic("intrinsic1");
                new MultiThread(flyweight).start();
                flyweight.setIntrinsic("intrinsic2");
                new MultiThread(flyweight).start();
            }
        }
    }
    View Code
    • 性能问题,尽量使用Java基本类型作为外部状态(即为key),如果自定义对象作为外部状态会降低系统执行的效率。
  • 相关阅读:
    Elasticsearch中父子表上传及查询使用
    python中的正则表达式使用案例
    MySQL函数使用案例大全
    Scrapy爬虫编写流程—以爬取智联为例
    GCD中的dispatch_get_global_queue(long identifier, unsigned long flags)
    (转载)iOS直播类APP开发流程
    MRC下NSNumber,NSString,及NSArray,NSMutableArray的引用计数,个人学习
    转载学习:tabbleView顶部图片的拉伸效果,
    转载学习:Objective-C常用的函数,
    转载--iOS,UIScrollView的相关属性,方法
  • 原文地址:https://www.cnblogs.com/zhanglei93/p/6112936.html
Copyright © 2011-2022 走看看