Résumé :
La technologie orientée objet peut résoudre certains problèmes de flexibilité ou d'évolutivité, mais dans de nombreux cas, il est nécessaire d’augmenter le nombre de classes et d’objets dans le système. Lorsqu'il y a trop d'objets, le coût de fonctionnement sera trop élevé, ce qui entraînera une dégradation des performances et d'autres problèmes. Mode FlyweightUtilisez la technologie de partage pour réutiliser des objets identiques ou similaires afin d'améliorer l'utilisation des ressources système. Cet article explique d'abord les problèmes à résoudre par le modèle flyweight et le concept de résolution de problèmes, puis se concentre sur l'essence du modèle du point de vue de la mise en œuvre, et donne en outre les rôles et la structure organisationnelle qu'il contient. Enfin, des exemples d'application et des scénarios d'utilisation du mode de partage sont donnés.
La technologie orientée objet peut bien résoudre certains problèmes de flexibilité ou d'évolutivité, mais dans de nombreux cas, elle doit être implémentée dans le système. le nombre de classes et d'objets. Lorsqu'il y a trop d'objets, le coût de fonctionnement sera trop élevé, ce qui entraînera une dégradation des performances et d'autres problèmes. Le modèle poids mouche est né pour résoudre ce type de problème. Le mode Flyweight réalise la réutilisation d'objets identiques ou similaires grâce à la technologie de partage. Le diagramme schématique est le suivant (nous pouvons partager un objet Hello world, dans lequel la chaîne « Hello world ». est l'état interne , peut être partagé ; la couleur de la police est un état externe, ne peut pas être partagée et est définie par le client) :
Le même contenu qui peut être partagé en mode poids mouche est appelé État interne (état intrinsèque) , et les contenus qui doivent être définis par l'environnement externe et ne peuvent pas être partagés sont appelés État extrinsèque (État extrinsèque) , où l'état externe et l'état interne sont indépendants l'un de l'autre, et les changements dans l'état externe n'entraîneront pas de changements dans l'état interne. En raison de la distinction entre l'état interne et l'état externe, le même objet peut avoir des caractéristiques différentes en définissant différents états externes, et le même état interne peut être partagé. En d'autres termes, L'essence du modèle poids mouche est la séparation et le partage : la séparation change et ne change pas, et le partage ne change pas. Divisez l'état d'un objet en état interne et état externe. L'état interne est inchangé et l'état externe change ; puis en partageant les parties inchangées, l'objectif de réduire le nombre d'objets et d'économiser de la mémoire est atteint ; .
En mode Flyweight, le Mode Usine apparaît généralement. Vous devez créer une usine Flyweight pour maintenir un pool de poids mouche (utilisé pour stocker des poids mouches avec le même méta-objet interne). En mode poids mouche, ce qui est partagé est l'état interne de l'objet poids mouche, et l'état externe doit être défini via l'environnement. En utilisation réelle, l'état interne qui peut être partagé est limité, de sorte que les objets flyweight sont généralement conçus pour être des objets plus petits contenant moins d'état interne. Ce type d'objet est également appelé Objet à grain fin. .
Le but du mode poids mouche est d'utiliser la technologie de partage pour parvenir à la réutilisation d'un grand nombre d'objets à granularité fine.
Modèle de poids mouche : utiliser la technologie de partage pour prendre en charge efficacement la réutilisation d'un grand nombre d'objets à grain fin. Le système n'utilise qu'un petit nombre d'objets, et ces objets sont très similaires et ont peu de changements d'état, de sorte que les objets peuvent être réutilisés plusieurs fois. Étant donné que le mode poids mouche exige que les objets pouvant être partagés soient des objets à granularité fine, il est également appelé mode léger. Il s'agit d'un mode structurel d'objet.
Modèle de poids mouche : Utilisez le partage pour prendre en charge efficacement un grand nombre d'objetsà granularité fine. 1. Personnages impliqués dans le mode
Flyweight : Flyweight interface , à travers laquelle l'état externe est transmis et utilisé
ConcreteFlyweight : Implémentation spécifique du poids mouche L'objet doit être partageable ; et doit encapsuler l'état interne de l'objet flyweight ;
UnsharedConcreteFlyweight : Objet d'implémentation flyweight non partagé, tous les objets flyweight ne peuvent pas être partagés, les objets Flyweight non partagés sont généralement des combinaisons d'objets flyweight
FlyweightFactory : Flyweight Factory est principalement utilisée pour créer et gérer des objets flyweight partagés et fournir des interfaces externes pour accéder aux objets flyweight partagés ;
Exemple d'implémentation :
//抽象享元角色类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('a')); fly.operation("First Call"); fly = factory.factory(new Character('b')); fly.operation("Second Call"); fly = factory.factory(new Character('a')); fly.operation("Third Call"); } }
Bien que le client ait demandé trois objets flyweight, le flyweight réellement créé Il n'y en a que deux des objets, c'est ce que signifie le partage. Les résultats d'exécution sont les suivants :
//抽象享元角色类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('a'); compositeState.add('b'); compositeState.add('c'); compositeState.add('a'); compositeState.add('b'); 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 = 'a'; Flyweight fly1 = flyFactory.factory(state); Flyweight fly2 = flyFactory.factory(state); System.out.println("单纯享元模式是否可以共享对象:" + (fly1 == fly2)); } }Les résultats d'exécution sont les suivants :
statique est généralement fournie . Pour renvoyer un objet poids mouche, utilisez Simple Factory Pattern pour générer un objet poids mouche
Dans un système, il n'y en a généralement qu'un. objet poids mouche Usine Yuan, doncLa classe d'usine poids mouche peut être conçue en utilisant le mode singleton
Le mode poids mouche peut être combiné avec le mode combinaison pour former composite partagé Le mode méta définit uniformément l'état externe des objets flyweight.
qui prend en compte les performances du système , vous pouvez économiser de l'espace mémoire et améliorer les performances du système en utilisant le mode poids mouche.
Le cœur du modèle de poids mouche est la classe d'usine de poids mouche. La fonction de la classe d'usine de poids mouche est de fournir un pool de poids mouche pour stocker les objets de poids mouche. un objet est nécessaire, il est d'abord obtenu à partir du pool de poids mouche. S'il n'existe pas dans le pool de poids mouche, un nouvel objet poids mouche est créé et renvoyé à l'utilisateur, et lenouveau objet est enregistré dans le pool de poids mouche. piscine de poids mouche. Code typique de classe d'usine de poids mouche :
Le mode poids mouche prend en charge efficacement un grand nombre d'objets à grain fin de manière partagée,
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; } } }La clé du partage d'objets flyweight est de faire la distinction entre l'état interne (Internal State) et l'état externe (External State).
Où :
Code poids mouche typique :
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、模式的实现
享元模式运用共享技术有效地支持大量 细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用,它是一种对象结构型模式。
享元模式包含四个角色:抽象享元类声明一个接口,通过它可以接受并作用于外部状态;具体享元类实现了抽象享元接口,其实例称为享元对象;非共享具体享元是不能被共享的抽象享元类的子类;享元工厂类用于创建并管理享元对象,它针对抽象享元类编程,将各种类型的具体享元对象存储在一个享元池中。
享元模式以共享的方式高效地支持大量的细粒度对象,享元对象能做到共享的关键是区分内部状态和外部状态。其中内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,因此内部状态可以共享;外部状态是随环境改变而改变的、不可以共享的状态。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!