デザインモードのメタモード---Pattern Flyweight


パターンの定義
享元モード(Flyweight Pattern)はストーク技術の重要な実現方式であり、その定義は以下の通りである.
Use sharing to support large numbers of fine-grained objects efficiently.
共有オブジェクトを用いることで、大量の細粒度のオブジェクトを効果的にサポートすることができる.
メタモードの定義は,細粒度のオブジェクトと共有オブジェクトの2つの要件を提案した.オブジェクトの割り当てが多すぎると、プログラムのパフォーマンスが低下し、メモリがオーバーフローしやすくなります.このような状況を回避することは,メタモードにおける共有技術を用いることである.
細粒度の状態は内部状態(instrinsic)と外部状態(extrinsic):内部状態:内部状態はオブジェクトが共有できる情報であり、メタオブジェクトの内部に格納され、環境の変化に伴って変化せず、共有可能な部分に属する.
外部状態:外部状態はオブジェクトが依存するタグであり、環境が変化するにつれて変化し、共有できない状態である.
を選択します.
構造クラス
モードの使用シーン
  • システムには、類似オブジェクト
  • が多数存在する.
  • 細粒度のオブジェクトはいずれも近い外部状態を備えており、内部状態は環境に関係なく、すなわちオブジェクトに特定のアイデンティティがない.
  • バッファプールが必要なシーン
  • メリットとデメリット
    享元モードは非常に簡単なモードで、アプリケーションが作成したオブジェクトを大幅に減らすことができ、プログラムのメモリの占有量を低減し、プログラムの性能を強化することができますが、同時にシステムの複雑さを高め、外部と内部の状態を分離する必要があります.また、外部の状態は内部の状態が変化するにつれて変化するべきではありません.そうでなければシステムの論理的混乱を招く.
    UMLクラス図
    ロールの紹介
  • Flyweight-抽象的な享元ロール
  • 簡単に言えば、オブジェクトの外部状態と内部状態のインタフェースまたは実装を定義する抽象クラスです.
  • ConcreteFlyweight-具体的なメタロール
  • 具体的な製品クラスでは、このロールで注意しなければならないのは、内部ステータス処理が環境に関係なく、内部ステータスを変更しながら外部ステータスを変更する操作は絶対に許されないことです.
  • unsharedConcreteFlyweight-共有できないメタロール
  • 外部状態が存在しない、またはセキュリティ要件が共有技術を使用できないオブジェクトは、通常、享元ファクトリには表示されません.
  • FlyweightFactory-享元工場
  • プールコンテナを構築し、プールからオブジェクトを取得する方法を提供します.
    享元モードの目的は共有技術を用いて、いくつかの細粒度のオブジェクトが共有できるようにし、細粒度のオブジェクトを多く使用し、再利用や再構築を容易にすることである.
    モードの汎用ソース
    Flyweight:
    
    public abstract class Flyweight {
        //    
        private String instrinsic;
        //    
        private final String extrinsic;
        //              
        public Flyweight(String extrinsic) {
            super();
            this.extrinsic = extrinsic;
        }
    
        public String getInstrinsic() {
            return instrinsic;
        }
    
        public void setInstrinsic(String instrinsic) {
            this.instrinsic = instrinsic;
        }
        //      
        public abstract void operate();
    
        @Override
        public String toString() {
            return "Flyweight [instrinsic=" + instrinsic + ", extrinsic="
                    + extrinsic + "]";
        }
    
    }

    ConcreteFlyweight1:
    
    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
            System.out.println("ConcreteFlyweight1----operate()");
        }
    
    }

    ConcreteFlyweight2:
    
    public class ConcreteFlyweight2 extends Flyweight {
    
    
        public ConcreteFlyweight2(String extrinsic) {
            super(extrinsic);
            // TODO Auto-generated constructor stub
        }
    
        @Override
        public void operate() {
            // TODO Auto-generated method stub
            System.out.println("ConcreteFlyweight2----operate()");
        }
    
    }
    

    FlyweightFactory:
    import java.util.HashMap;
    
    
    public class FlyweightFactory {
        //       
        private static HashMap<String, Flyweight> pool = new HashMap<String, Flyweight>();
        //    
        public static Flyweight getFlyweight(String Extrinsic){
            Flyweight flyweight = null;
            if(pool.containsKey(Extrinsic)){
                flyweight = pool.get(Extrinsic);
            }else {
                flyweight = new ConcreteFlyweight1(Extrinsic);
                pool.put(Extrinsic, flyweight);
            }
            return flyweight;
        }
        //         
        public static void printPool(){
            for (int i = 0; i < pool.size(); i++) {
                System.out.println(":"+pool.get("indext:"+i));
            }
        }
    }

    Client:
    
    public class Client {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Flyweight flyweight = null;
            for (int i = 0; i < 3; i++) {
                flyweight = FlyweightFactory.getFlyweight("indext:"+i);
                flyweight.operate();
            }
            FlyweightFactory.printPool();
            System.out.println("------------------------");
    
            for (int i = 0; i < 3; i++) {
                flyweight = FlyweightFactory.getFlyweight("indext:"+i);
                flyweight.operate();
            }
            FlyweightFactory.printPool();
        }
    
    }
    

    出力結果:
    ConcreteFlyweight1----operate()
    ConcreteFlyweight1----operate()
    ConcreteFlyweight1----operate()
    :Flyweight [instrinsic=null, extrinsic=indext:0]
    :Flyweight [instrinsic=null, extrinsic=indext:1]
    :Flyweight [instrinsic=null, extrinsic=indext:2]
    ------------------------ ConcreteFlyweight1----operate() ConcreteFlyweight1----operate() ConcreteFlyweight1----operate() :Flyweight [instrinsic=null, extrinsic=indext:0] :Flyweight [instrinsic=null, extrinsic=indext:1] :Flyweight [instrinsic=null, extrinsic=indext:2]

    結果から,プール技術のバッファリング法は確かにFlyweightの数を増やしていないことが分かった.
    Androidソースでのモード実装
    雑談
    参考資料
    (1).設計モードの禅—第28章享元モード(2)享元モードhttps://github.com/simple-android-framework/android_design_patterns_analysis/tree/master/flyweight