Home  >  Article  >  Java  >  In-depth understanding of flyweight mode sample code (pictures and text)

In-depth understanding of flyweight mode sample code (pictures and text)

黄舟
黄舟Original
2017-03-14 10:22:241091browse


Abstract

 Object-oriented technology can well solve some flexibility or Scalability issues, but in many cases it is necessary to increase the number of classes and objects in the system. When there are too many objects, the running cost will be too high, resulting in performance degradation and other problems. Flyweight ModeUse sharing technology to achieve reuse of the same or similar objects to improve the utilization of system resources. This article first explains the problems to be solved by the flyweight model and the concept of problem solving, then focuses on the essence of the model from an implementation perspective, and further gives the roles and organizational structure it contains. Finally, application examples and usage scenarios of the sharing mode are given.


1. Motivation

 Object-oriented technology can solve some flexibility or scalability problems well, but in many cases it needs to be implemented in the system Increase the number of classes and objects. When there are too many objects, the running cost will be too high, resulting in performance degradation and other problems. The flyweight model was born to solve this type of problem. Flyweight mode realizes the reuse of the same or similar objects through sharing technology. The schematic diagram is as follows (we can share a Hello world object, in which string "Hello world" is the internal state , can be shared; the font color is an external state, cannot be shared, and is set by the client):

##          

In-depth understanding of flyweight mode sample code (pictures and text)

The same content that can be shared in flyweight mode is called

Internal State (Intrinsic State), and those contents that need to be set by the external environment and cannot be shared are called External State (Extrinsic State), where the external state and the internal state are independent of each other, and changes in the external state will not cause changes in the internal state. Due to the distinction between internal state and external state, the same object can have some different characteristics by setting different external states, and the same internal state can be shared. In other words, The essence of the flyweight model is separation and sharing: separation of change and change, and sharing of change. Divide the state of an object into internal state and external state. The internal state is unchanged and the external state changes; then by sharing the unchanged parts, the purpose of reducing the number of objects and saving memory is achieved.

In the flyweight mode,

Factory mode usually appears. It is necessary to create a flyweight factory to be responsible for maintaining a flyweight pool (Flyweight Pool) (used to store flyweights with the same internal state). meta-object). In the flyweight mode, what is shared is the internal state of the flyweight object, and the external state needs to be set through the environment. In actual use, the internal state that can be shared is limited, so flyweight objects are generally designed to be smaller objects that contain less internal state. This kind of object is also called fine-grained Object.
The purpose of the flyweight pattern is to use sharing technology to achieve the reuse of a large number of fine-grained objects.


2. Definition and structure

Flyweight Pattern: Use sharing technology to effectively support the reuse of a large number of fine-grained objects. The system only uses a small number of objects, and these objects are very similar and have little state changes, so the objects can be reused multiple times. Since

Flyweight mode requires that objects that can be shared must be fine-grained objects, it is also called lightweight mode, which is an object structure mode.

Flyweight Pattern:

Use sharing to support large numbers of fine-grained objects efficiently.


1. Roles involved in the model

 Flyweight: FlyweightInterface, through this interface the external state is passed in and acts on the external state;
 ConcreteFlyweight: Specific flyweight implementation The object must be shareable and needs to encapsulate the internal state of the flyweight object;
UnsharedConcreteFlyweight: Non-shared flyweight implementation object, not all flyweight objects can be shared, non-shared Flyweight objects are usually combinations of flyweight objects;
FlyweightFactory: Flyweight factory is mainly used to create and manage shared flyweight objects and provide external interfaces for accessing shared flyweight objects;


2. Pattern structure

: In the pure flyweight mode, all flyweight objects are shareable, that is, all subclasses of the abstract flyweight class can be shared, and there is no non-shared concrete flyweight class. Flyweight Structure.png-72.6kB

         

Implementation example:

  • //抽象享元角色类public interface Flyweight {
        //一个示意性方法,参数state是外蕴状态
        public void operation(String state);
    }//具体享元角色类//具体享元角色类ConcreteFlyweight有一个内蕴状态,在本例中一个Character类型的intrinsicState属性代表,它的值应当在享元对象
    //被创建时赋予。所有的内蕴状态在对象创建之后,就不会再改变了。如果一个享元对象有外蕴状态的话,所有的外部状态都必须存储在客户端,
    //在使用享元对象时,再由客户端传入享元对象。这里只有一个外蕴状态,operation()方法的参数state就是由外部传入的外蕴状态。
    public class ConcreteFlyweight implements Flyweight {
        private Character intrinsicState = null;    /**
         * 构造函数,内蕴状态作为参数传入
         * @param state
         */
        public ConcreteFlyweight(Character state){        this.intrinsicState = state;
        }    /**
         * 外蕴状态作为参数传入方法中,改变方法的行为,
         * 但是并不改变对象的内蕴状态。
         */
        @Override
        public void operation(String state) {        // TODO Auto-generated method stub
            System.out.println("Intrinsic State = " + this.intrinsicState);
            System.out.println("Extrinsic State = " + state);
        }
    
    }//享元工厂角色类//享元工厂角色类,必须指出的是,客户端不可以直接将具体享元类实例化,而必须通过一个工厂对象,利用一个factory()方法得到享元对象。
    //一般而言,享元工厂对象在整个系统中只有一个,因此也可以使用单例模式。
    //当客户端需要单纯享元对象的时候,需要调用享元工厂的factory()方法,并传入所需的单纯享元对象的内蕴状态,由工厂方法产生所需要的//享元对象。
    public class FlyweightFactory {
        private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();    
        public Flyweight factory(Character state){        
        //先从缓存中查找对象
            Flyweight fly = files.get(state);        
            if(fly == null){            
            //如果对象不存在则创建一个新的Flyweight对象
                fly = new ConcreteFlyweight(state);            
                //把这个新的Flyweight对象添加到缓存中
                files.put(state, fly);
            }        return fly;
        }
    }//客户端类public class Client {
    
        public static void main(String[] args) {        // TODO Auto-generated method stub
            FlyweightFactory factory = new FlyweightFactory();
            Flyweight fly = factory.factory(new Character(&#39;a&#39;));
            fly.operation("First Call");
    
            fly = factory.factory(new Character(&#39;b&#39;));
            fly.operation("Second Call");
    
            fly = factory.factory(new Character(&#39;a&#39;));
            fly.operation("Third Call");
        }
    
    }

     

    Although the client applied for three flyweight objects, the actual created flyweight objects are only Two, that's what sharing means.

    The running results are as follows:In-depth understanding of flyweight mode sample code (pictures and text)
           

Compound flyweight mode: use some simple flyweights

combination mode

By combining them, composite flyweight objects can be formed. Such composite flyweight objects themselves cannot be shared, but they can be decomposed into simple flyweight objects, and the latter can be shared. In-depth understanding of flyweight mode sample code (pictures and text)

                       
    ## Implementation example:
  • //抽象享元角色类public interface Flyweight {
        //一个示意性方法,参数state是外蕴状态
        public void operation(String state);
    }//具体享元角色类
    //具体享元角色类ConcreteFlyweight有一个内蕴状态,在本例中一个Character类型的intrinsicState属性代表,它的值应当在享元对象
    //被创建时赋予。所有的内蕴状态在对象创建之后,就不会再改变了。如果一个享元对象有外蕴状态的话,所有的外部状态都必须存储在客户端,
    //在使用享元对象时,再由客户端传入享元对象。这里只有一个外蕴状态,operation()方法的参数state就是由外部传入的外蕴状态。
    public class ConcreteFlyweight implements Flyweight {
        private Character intrinsicState = null;    /**
         * 构造函数,内蕴状态作为参数传入
         * @param state
         */
        public ConcreteFlyweight(Character state){        this.intrinsicState = state;
        }    /**
         * 外蕴状态作为参数传入方法中,改变方法的行为,
         * 但是并不改变对象的内蕴状态。
         */
        @Override
        public void operation(String state) {        // TODO Auto-generated method stub
            System.out.println("Intrinsic State = " + this.intrinsicState);
            System.out.println("Extrinsic State = " + state);
        }
    
    }
    //复合享元角色类
    //复合享元对象是由单纯享元对象通过复合而成的,因此它提供了add()这样的聚集管理方法。由于一个复合享元对象具有不同的聚集元素,
    //这些聚集元素在复合享元对象被创建之后加入,这本身就意味着复合享元对象的状态是会改变的,因此复合享元对象是不能共享的。
    //复合享元角色实现了抽象享元角色所规定的接口,也就是operation()方法,这个方法有一个参数,代表复合享元对象的外蕴状态。
    //一个复合享元对象的所有单纯享元对象元素的外蕴状态都是与复合享元对象的外蕴状态相等的;
    //而一个复合享元对象所含有的单纯享元对象的内蕴状态一般是不相等的,不然就没有使用价值了。
    public class ConcreteCompositeFlyweight implements Flyweight {
    
        private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();    /**
         * 增加一个新的单纯享元对象到聚集中
         */
        public void add(Character key , Flyweight fly){
            files.put(key,fly);
        }    /**
         * 外蕴状态作为参数传入到方法中
         */
        @Override
        public void operation(String state) {
            Flyweight fly = null;        for(Object o : files.keySet()){
                fly = files.get(o);
                fly.operation(state);
            }
    
        }
    
    }//享元工厂角色类//享元工厂角色提供两种不同的方法,一种用于提供单纯享元对象,另一种用于提供复合享元对象。public class FlyweightFactory {
        private Map<Character,Flyweight> files = new HashMap<Character,Flyweight>();    /**
         * 复合享元工厂方法
         */
        public Flyweight factory(List<Character> compositeState){
            ConcreteCompositeFlyweight compositeFly = new ConcreteCompositeFlyweight();        for(Character state : compositeState){
                compositeFly.add(state,this.factory(state));
            }        return compositeFly;
        }    /**
         * 单纯享元工厂方法
         */
        public Flyweight factory(Character state){        //先从缓存中查找对象
            Flyweight fly = files.get(state);        if(fly == null){            //如果对象不存在则创建一个新的Flyweight对象
                fly = new ConcreteFlyweight(state);            //把这个新的Flyweight对象添加到缓存中
                files.put(state, fly);
            }        return fly;
        }
    }//客户端类public class Client {
    
        public static void main(String[] args) {
            List<Character> compositeState = new ArrayList<Character>();
            compositeState.add(&#39;a&#39;);
            compositeState.add(&#39;b&#39;);
            compositeState.add(&#39;c&#39;);
            compositeState.add(&#39;a&#39;);
            compositeState.add(&#39;b&#39;);
    
            FlyweightFactory flyFactory = new FlyweightFactory();
            Flyweight compositeFly1 = flyFactory.factory(compositeState);
            Flyweight compositeFly2 = flyFactory.factory(compositeState);
            compositeFly1.operation("Composite Call");
    
            System.out.println("---------------------------------");        
            System.out.println("复合享元模式是否可以共享对象:" + (compositeFly1 == compositeFly2));
    
            Character state = &#39;a&#39;;
            Flyweight fly1 = flyFactory.factory(state);
            Flyweight fly2 = flyFactory.factory(state);
            System.out.println("单纯享元模式是否可以共享对象:" + (fly1 == fly2));
        }
    }

    The running results are as follows:        

    In-depth understanding of flyweight mode sample code (pictures and text)

Combined use of flyweight mode with other modes

In the flyweight factory class of flyweight mode, a

static

factory method is usually provided for return Flyweight objects, use

In-depth understanding of flyweight mode sample code (pictures and text)

Simple factory pattern
to generate flyweight objects
  • ;

    In a system, there is usually only one flyweight factory , so

    Flyweight factory class can be designed using singleton pattern Flyweight pattern can be combined with combination pattern to form composite flyweight pattern , uniformly setting the external state of the flyweight object.

    3. Pattern Analysis

    Flyweight pattern is a design that considers system performance. Mode, by using flyweight mode, you can save memory space and improve system performance.

 

The core of the flyweight model is the flyweight factory class. The function of the flyweight factory class is to provide a flyweight pool for storing flyweight objects. Users When an object is needed, first obtain it from the flyweight pool. If it does not exist in the flyweight pool, create a new flyweight object and return it to the user, and save the

New

object in the flyweight pool. Typical flyweight factory class code:

public class FlyweightFactory{
    private HashMap flyweights = new HashMap();    public Flyweight getFlyweight(String key)
    {        if(flyweights.containsKey(key))
        {            return (Flyweight)flyweights.get(key);
        }        else
        {
            Flyweight fw = new ConcreteFlyweight();
            flyweights.put(key,fw);            return fw;
        }
    }
}
Flyweight mode efficiently supports a large number of fine-grained objects in a shared way,

The key to enabling meta-object sharing is to distinguish between internal state (Internal State) and external state (External State). Among them:

Internal state

is a state stored inside the flyweight object and will not change with the environment, so the internal state can shared.

External state is a state that changes with the environment and cannot be shared. The external state of the flyweight object must be saved by the client and passed into the flyweight object when it is needed after the flyweight object is created. One external state is independent of another external state.

  • Typical flyweight code:

    public class Flyweight{
            //内部状态作为成员属性
        private String intrinsicState;    public Flyweight(String intrinsicState)
        {        this.intrinsicState = intrinsicState;
        }    public void operation(String extrinsicState)
        {
            ......
        }   
    }

    四. 模式的应用

    • 享元模式在编辑器软件中大量使用,如在一个文档中多次出现相同的图片,则只需要创建一个图片对象,通过在应用程序中设置该图片出现的位置,可以实现该图片在不同地方多次重复显示。

    • 广义上讲,在JDK类库中定义的String类也是使用享元模式的典型。

    public class Demo{
        public static void main(String args[])
        {
            String str1 = "abcd";
            String str2 = "abcd";
            String str3 = "ab" + "cd";
            String str4 = "ab";
            str4 += "cd";
            System.out.println(str1 == str2);      //true
            System.out.println(str1 == str3);      //true
            System.out.println(str1 == str4);      //false
        }
    }

    五. 总结

    1、模式适用环境
      
    在以下情况下可以使用享元模式:

    • 一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费;

    • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中(细粒度对象);

    • 使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费资源,因此,应当在多次重复使用享元对象时才值得使用享元模式。


    2、模式的优点

      (1)它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份;
      (2)享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享。


    3、模式的缺点

      (1)享元模式使得系统更加复杂,需要分离出内部状态和外部状态,这使得程序的逻辑复杂化;
      (2)为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。


    4、模式的实现

    • 享元模式运用共享技术有效地支持大量 细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用,它是一种对象结构型模式。

    • 享元模式包含四个角色:抽象享元类声明一个接口,通过它可以接受并作用于外部状态;具体享元类实现了抽象享元接口,其实例称为享元对象;非共享具体享元是不能被共享的抽象享元类的子类;享元工厂类用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中。

    • 享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态和外部状态。其中内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享;外部状态是随环境改变而改变的、不可以共享的状态。

The above is the detailed content of In-depth understanding of flyweight mode sample code (pictures and text). For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn