記事のディレクトリ
1.基本的な紹介
1.定義
FlyWeightモード(FlyWeight)は、フライウェイトモードとも呼ばれ、再利用されるきめの細かいオブジェクトが多数ある場合によく使用されます。それは本質的に共有技術です。
2.利点
Flyweightプールを使用することにより、ユーザーはオブジェクトを呼び出すときにnewに移動する必要がなく、Flyweightプールから直接取得するだけで、メモリスペースを節約できます。
注:太多的对象不仅会影响性能,更严重的情况下可能会造成内存溢出
3.デメリット
1)ロジックはより複雑になります。
2)Flyweightプールから直接取り出せないオブジェクトについては、新規に移動する必要がありますが、現時点では、Flyweightモードを使用してオブジェクトを取得するのに時間がかかります。
4.役割
1)抽象的なフライ級クラス
インターフェイス/抽象クラス
2)特定のフライ級クラス
インターフェイスまたは抽象クラスを実装する具象サブクラス。これらのサブクラスは頻繁に再利用され、これらのサブクラスオブジェクトはきめ細かくなります。
3)フライ級ファクトリークラス
工場は実際にはフライ級プールです
4)コンビネーションフライ級クラス
結合フライ級クラスは、基本的なフライ級クラスに依存する全体的なクラスです。たとえば、フライ級プールに文字AとBがある場合、これら2つの文字オブジェクトを実際に使用して、結合フライ級であるAB文字列を形成できます。クラス。
5.内部状態と外部状態
きめの細かいオブジェクトは、オブジェクトの数が多い場合、必然的に類似しています。非常に多くの異なるきめの細かいオブジェクトを区別するにはどうすればよいですか?現時点では、これらのオブジェクトの情報を内部状態と内部状態の2つの部分に分けます。外部状態。
- 内部状態とは、オブジェクトによって共有される情報を指します。この情報は、flyweightオブジェクトに格納されており、環境の変化によって変化することはありません。
- 外部状態とは、オブジェクトが信頼できるマークのことで、環境によって変化し、共有できない状態です。
如何理解内部状态和外部状态呢?
たとえば、戦車戦では、弾丸の種類が異なり、内部の状態によって変化します。たとえば、焼夷弾か発煙弾かは、内部の状態によって異なります。しかし、私たちの戦車はさまざまな方向に弾丸を発射することができ、弾丸の方位角座標は弾丸の外部状態です。
もう1つの例は、黒と白のピースが2つしかないGoです。内部状態は色を制御し、外部状態はゲーム内のチェスの位置を制御します。
2、アプリケーションシナリオ
1.スレッドプール
2、文字列
JVMには文字列定数プールがあります。たとえば、String = "a"の場合、直接ヒープにはありませんが、
new String("a")
最初にクエリのために定数プールに移動します。定数プールに "a"がある場合、定数プール内の文字列「a」の参照アドレスを直接返します。文字列の追加は、実際にはStringBuilder()のappendを呼び出してから、toStringを呼び出すため、追加された参照は定数プールではなくヒープにあります。
3、整数
整数では、いくつかの既存のオブジェクト(-128,127)もあり、これらのオブジェクトはバッファに入れられます。
Integer a=1;
またはを使用Integer a=Integer.ValueOf(1)
すると、最初にバッファ内のオブジェクトと一致します。バッファにある場合は、直接返されます。バッファにオブジェクトがありません。たとえば、128がバッファにない場合は、次のことができます。return Integer a=new Integer(128);
4.ゴバン
五目並べゲームでは、合計500個以上の黒と白の石が必要な場合、フライ級モードやシングルトンモードを使用せずに500個以上のオブジェクトが必要です
new
。ただし、フライ級モードを使用する場合、オブジェクトは2つしかありません。:1つの黒チェス、1つの白いチェス。[注:单例模式也可以实现]
、これにより、メモリスペースが大幅に節約され、新しい時間も節約されます。スペースと時間のパフォーマンスが大幅に向上しました。
3、他のモードで使用
通常、関連付けられたフライパターン单例模式
、组合模式
、工厂模式
使用しました。
1)シングルトンモード
工場ではシングルトンモードを使用できます。(前提是工厂不是泛型工厂
)
2)コンビネーションモード
複合フライ級モデルは、組み合わせモデルを使用します
3)工場モデル
工場は実際にはフライ級プールです
4、コード分析
//抽象的なフライ級
package pattern.flyweight;
public abstract class FlyWeight {
//内部状态
String instate;
//外部状态
String outstate;
public FlyWeight(String outstate) {
this.instate=outstate;
}
//与外部状态相关的逻辑操作
abstract void operation();
//获取或者设置内部状态
public String getInstate() {
return instate;
}
public void setInstate(String instate) {
this.instate = instate;
}
}
//具体享元
package pattern.flyweight;
public class A extends FlyWeight{
public A(String outstate) {
super(outstate);
// TODO Auto-generated constructor stub
}
//根据外部状态进行一系列的逻辑操作
@Override
void operation() {
// TODO Auto-generated method stub
System.out.println(outstate);
}
}
//フライ級ファクトリー
package pattern.flyweight;
import java.util.HashMap;
import java.util.Map;
//泛型时,不能用单例模式,否则泛型将会没有意义
public class FlyWeightFactory {
private FlyWeightFactory() {
};
// volatile是避免重排序
private static volatile FlyWeightFactory INSTANCE = null;
public static FlyWeightFactory getINSTANCE() {
if (INSTANCE == null) {
synchronized (FlyWeightFactory.class) {
if (INSTANCE == null)
INSTANCE = new FlyWeightFactory();
}
}
return INSTANCE;
}
static Map<Character,FlyWeight> FlyWeightMap=new HashMap<Character,FlyWeight>();
public FlyWeight getConcreteFlyWeight(char c) {
if(!FlyWeightMap.containsKey(c))
FlyWeightMap.put(c,new A());
return FlyWeightMap.get(c);
}
}
//テストクラス
package pattern.flyweight;
public class Main {
public static void main(String[] args) {
/*
* Integer a=Integer.valueOf(3);//有缓存机制 Integer c=new Integer(3);//没有用到缓存机制
* Integer b=new Integer(3); Integer d=3;//有用到缓存机制 Integer e=129; Integer
* f=129;//超过了缓存池 System.out.println(a==d); System.out.println(e==d);
* System.out.println(c==b);
*
* String a0="a"; String a1="b"; String a2="a"+"b"; String b="ab"; String
* c="ab"; String a=a0+a1;
* System.out.println(a==b);//字符串相加其实是StringBuilder.append()然后toString
* System.out.println(a.intern()==b);//intern是找常量池中的引用
* System.out.println(b==c);//两个都指向常量池中
* System.out.println(a2==b);//如果是定义的时候直接相加,编译器会进行优化,直接看成String a2="ab";
*/
FlyWeight a=FlyWeightFactory.getINSTANCE().getConcreteFlyWeight('a',"outstate");
FlyWeight b=FlyWeightFactory.getINSTANCE().getConcreteFlyWeight('a',"outstate");
System.out.println(a==b);
}
}
UML图:
フライ級モードを数行のコードで説明するのは非常に難しく、より適切な例が見つからないため、ここでは基本的なフライ級モードを簡単に紹介するだけです。この記事のテストでは、aとbが参照するかどうかのみをテストします。同じリファレンスを参照してください。一部の比較的小さなプログラムでのFlyweightモードの利点を反映するのは非常に困難です。それでも疑問がたくさんある場合は、Javaソースコードを確認できます。スレッドプールと整数バッファはすべて非常に有効です。フライ級モードの。