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

    享元模式(FlyWeight),其含义是运用共享技术有效地支持大量细粒度的对象,即系统只使用少量的对象,而这些对象都相近,状态变化很小,对象使用次数却很多。

    享元模式能做到共享的关键是区分内蕴状态和外蕴状态,一个内蕴状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的。因此一个享元可以具有内蕴状态并可以共享。一个外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态不可以影响享元对象的内蕴对象。换句话说,它们是互相独立的。

    其适用性:

    一个应用程序使用了大量的对象,

    完全由于使用大量的对象,造成很大的存储开销,

    对象的大多数状态都可变为外部状态,

    如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,

    应用程序不依赖于对象标识。由于Flyweight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

      结构如下:

               

      享元模式在使用时分为单纯享元模式和复合享元模式两种,单纯享元模式中Flyweight都是可共享的,也是现在Flyweight实现的较多实例。现在先列出单纯享元模式:

     Flyweight.java

    package org.designpattern.structural.flyweight;

        public abstract class Flyweight {
             protected Character intrinsicState;

             protected Flyweight(Character intrinsicState){
                 this.intrinsicState = intrinsicState;
             };
             public abstract  void  operation(String extrinsicState);
             public Character getIntrinsicState(){
                 return this.intrinsicState;
             };
         }

      ConcreteFlyweight.java继承了Flyweight,实现了一个operation方法,类略。Flyweight是通过工厂得到的,下面是FlyweightFactory.java

    package org.designpattern.structural.flyweight;
    import java.util.HashMap;

    public class FlyweightFactory {
        private HashMap flyWeights;
           public FlyweightFactory(){
             flyWeights = new HashMap();
        }
        public Flyweight getFlyweight(Character key){
             if(this.flyWeights.containsKey(key)){
                System.out.println(key + " already created!");
                return (Flyweight) flyWeights.get(key);
            }else{
                 Flyweight flyweight = new ConcreteFlyweight(key);
                 flyWeights.put(key,flyweight);
                 return flyweight;
            }
        }

      如果是单纯享元模式,到这里再加上客户测试类就结束了。如果使用复合享元模式,复合元素的对象的状态是会改变的,所以复合享元对象是不能共享的。需要再增加一个类UnsharedConcreteFlyeweight.java

    public class UnsharedConcreteFlyweight extends Flyweight {

        private HashMap<Character,Flyweight> unsharedFlyweights;
        private Flyweight  flyweight;

        public UnsharedConcreteFlyweight(Character intrinsicState) {
            super(intrinsicState);
            this.unsharedFlyweights = new HashMap(20);
        }

        public void add(Character key,Flyweight flyweight){
            this.unsharedFlyweights.put(key,flyweight);
        }
        @Override
        public void operation(String extrinsicState) {
            System.out.println("extrinsicState:" + extrinsicState);
            Iterator<Map.Entry<Character,Flyweight>> it = unsharedFlyweights.entrySet().iterator();
            while(it.hasNext()){
                Map.Entry<Character,Flyweight> entry = it.next();
                Flyweight fly = entry.getValue();
                fly.operation(extrinsicState);
            }
        }

       } 

    此时在FlyweighFactory.java中需要增加一个方法支持不可共享的Flyweight的调用:

     public Flyweight getUnsharedFlyweight(String keys ){

            UnsharedConcreteFlyweight unsharedConcreteFlyweight = new UnsharedConcreteFlyweight(null);
            for(int i=0;i<keys.length();i++){
                Character character = new Character(keys.charAt(i));
                unsharedConcreteFlyweight.add(character,getFlyweight(character));
            }
            return unsharedConcreteFlyweight;

        }

     下面是客户测试类:

       package org.designpattern.structural.flyweight;
       public class Main {
        public static void main(String[] args) {
            FlyweightFactory factory = new FlyweightFactory();
            Flyweight fly1 = factory.getFlyweight('a');
            fly1.operation("First call!");
            Flyweight fly2 = factory.getFlyweight('b');
            fly2.operation("Second call!");
            Flyweight fly3 = factory.getFlyweight('a');
            fly3.operation("Third call!");
            System.out.println(fly1 == fly3);

            Flyweight unsharedFlyweight = factory.getUnsharedFlyweight("abcde");
            unsharedFlyweight.operation("Forth call!");
         }

      } 

     享元模式的有效性很大程度上取决于在何种情景下使用它,其主要缺点是使系统设计变得更加复杂,将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。我们通常会把Flyweight工厂设计为单例模式,其可以和许多模式共同使用更有效。

  • 相关阅读:
    Centos LNMP 安装日记
    记录一次开源工单系统
    搭建Lvs负载均衡群集
    使用yum配置lnmp环境(CentOS7.6)
    AWK的介绍学习
    Shell应用之网卡流量监测
    【NLP】RNN、LSTM、GRU
    【机器学习】Softmax及求导
    【PyTorch】使用中注意事项
    【实作】CNN-人脸表情识别
  • 原文地址:https://www.cnblogs.com/kingcucumber/p/3221331.html
Copyright © 2011-2022 走看看