Légysúly (tervezési minta)

Az oldal jelenlegi verzióját még nem ellenőrizték tapasztalt közreműködők, és jelentősen eltérhet a 2016. július 4-én felülvizsgált verziótól ; az ellenőrzések 23 szerkesztést igényelnek .
opportunista
Légysúly
Típusú szerkezeti
Leírása: Tervezési minták Igen

A flyweight ( eng.  flyweight , „lightweight (element)”) olyan szerkezeti tervezési minta , amelyben egy objektum, amely a program különböző helyein egyedi példányként jelenik meg, valójában nem az.

Cél

Memóriaoptimalizálás azáltal, hogy megakadályozza a közös entitással rendelkező elemek példányainak létrehozását.

Leírás

A Flyweight-t a költségek csökkentésére használják nagyszámú kis tárgy kezelésekor. A Flyweight tervezésénél meg kell osztani tulajdonságait külsőre és belsőre. A belső tulajdonságok mindig változatlanok, míg a külső tulajdonságok az alkalmazás helyétől és kontextusától függően eltérőek lehetnek, ezért azokat a szerelőn kívülre kell helyezni.

A Flyweight úgy egészíti ki a Factory Method sablont , hogy amikor egy ügyfél egy Factory Methodot hív meg egy új objektum létrehozásához, akkor egy már létrehozott objektumot keres a szükséges paraméterekkel, és visszaküldi a kliensnek. Ha nincs ilyen objektum, akkor a gyár újat hoz létre.

Példák

Python példa

Forráskód Pythonban osztály Lámpa ( objektum ): def __init__ ( self , color ): self . szín = szín osztály LámpaGyár : lámpák = dict () @staticmethod def get_lamp ( color ): return LampFactory . lámpák . beállított alapértelmezett ( szín , lámpa ( szín )) osztály TreeBranch ( objektum ): def __init__ ( self , branch_number ): self . ág_szám = ág_szám def hang ( self , lamp ): print ( f "Akaszt $ { lámpa . color } [$ { id ( lamp ) } ] lamp on branch $ { self . branch_number } [$ { id ( self ) } ]" ) osztály Karácsonyfa ( objektum ): def __init__ ( self ): self . lamps_hung = 0 self . ágak = {} def get_branch ( self , number ): önmagát adja vissza . ágak . setdefault ( szám , TreeBranch ( szám )) def dress_up_the_tree ( self ): self . hang_lamp ( "piros" , 1 ) én . hang_lamp ( "kék" , 1 ) én . hang_lamp ( "sárga" , 1 ) én . hang_lamp ( "piros" , 2 ) én . hang_lamp ( "kék" , ​​2 ) én . hang_lamp ( "sárga" , 2 ) én . hang_lamp ( "piros" , 3 ) én . hang_lamp ( "kék" , 3 ) én . hang_lamp ( "sárga" , 3 ) én . hang_lamp ( "piros" , 4 ) én . hang_lamp ( "kék" , 4 ) én . hang_lamp ( "sárga" , 4 ) én . hang_lamp ( "piros" , 5 ) én . hang_lamp ( "kék" , 5 ) én . hang_lamp ( "sárga" , 5 ) én . hang_lamp ( "piros" , 6 ) self . hang_lamp ( "kék" , 6 ) én . hang_lamp ( "sárga" , 6 ) én . hang_lamp ( "piros" , 7 ) én . hang_lamp ( "kék" , 7 ) én . hang_lamp ( "sárga" , 7 ) def hang_lamp ( saját , szín , ág_szám ): saját . get_branch ( ág_szám ) . lefagy ( LámpaFactory . get_lamp ( color )) self . lámpák_függesztett += 1 if __name__ == '__main__' : Karácsonyfa () . öltöztesd fel a fát ()

Python példa (konstruktor felülírással)

Python forráskód (konstruktor felülírással) osztály Lámpa ( objektum ): __instances = dict () def __new__ ( cls , color ): return cls . __példányok . setdefault ( color , super ( ) . __new__ ( cls )) def __init__ ( self , color ): self . szín = szín osztály TreeBranch ( objektum ): def __init__ ( self , branch_number ): self . ág_szám = ág_szám def hang ( self , lamp ): print ( f "Akaszt $ { lámpa . color } [$ { id ( lamp ) } ] lamp on branch $ { self . branch_number } [$ { id ( self ) } ]" ) osztály Karácsonyfa ( objektum ): def __init__ ( self ): self . lamps_hung = 0 self . ágak = {} def get_branch ( self , number ): önmagát adja vissza . ágak . setdefault ( szám , TreeBranch ( szám )) def dress_up_the_tree ( self ): az ( 1 , 8 ) tartomány ágához : "piros" színben , " kék " , "sárga " : saját . hang_lamp ( szín , ág ) def hang_lamp ( saját , szín , ág_szám ): saját . get_branch ( ág_szám ) . lógni ( Lámpa ( szín )) én . lámpák_függesztett += 1 if __name__ == '__main__' : Karácsonyfa () . öltöztesd fel a fát ()

1. példa Java-ban

Java forrás import java.util.* ; public enum FontEffect { BOLD , DŐLT , FELIRAT , ELŐFIZETÉS , ÁTTÖRZÉS } public final class FontData { /** * A gyenge hash-leképezés eldobja a nem használt hivatkozásokat a FontData-ra. * Az értékeket WeakReferences-be kell csomagolni, * mert a gyenge hash térképen lévő értékobjektumokat erős hivatkozások tartják. */ privát statikus végleges WeakHashMap < FontData , WeakReference < FontData >> flyweightData = new WeakHashMap < FontData , WeakReference < FontData >> (); privát végső int pontMéret ; privát végleges String fontFace ; privát végleges Szín szín ; private final < FontEffect > effektek beállítása ; private FontData ( int pointSize , String fontFace , Color color , EnumSet < FontEffect > Effects ) { this . pointSize = pointSize ; ezt . fontFace = fontFace ; ezt . szín = szín ; ezt . effektusok = Gyűjtemények . unmodifiableSet ( effektusok ); } public static FontData létrehozása ( int pointSize , String fontFace , Color color , FontEffect ... effektusok ) { EnumSet < FontEffect > effectsSet = EnumSet . noneOf ( FontEffect . osztály ); EffectSet . addAll ( Tömbök . asList ( effektusok )); // Nem foglalkozunk az objektumok létrehozásának költségeivel, csökkentjük a teljes memóriafelhasználást FontData data = new FontData ( pointSize , fontFace , color , effectsSet ); if ( ! flyweightData . includeKey ( data )) { flyweightData . put ( adat , new WeakReference < FontData > ( adat )); } // visszaadja az egyetlen megváltoztathatatlan másolatot a megadott értékekkel return flyweightData . kap ( adat ). kap (); } @Override public logikai egyenlő ( Object obj ) { if ( obj instanceof FontData ) { if ( obj == this ) { return true ; } FontData other = ( FontData ) obj ; vissza más . pointSize == pointSize && egyéb . fontFace . egyenlő ( fontFace ) && egyéb . szín . egyenlő ( szín ) && egyéb . hatások . egyenlő ( hatások ); } return false ; } @Override public int hashCode () { return ( pointSize * 37 + effektusok . hashCode () * 13 ) * fontFace . hashCode (); } // Getterek a betűtípusadatokhoz, de nem beállítók. A FontData megváltoztathatatlan. }

2. példa Java-ban

Java forrás nyilvános absztrakt osztály _ _ védett karakter szimbólum ; védett in szélesség ; védett belmagasság ; _ public abstract void printCharacter (); } public class CharacterA kiterjeszti EnglishCharacter { public CharacterA (){ symbol = 'A' ; szélesség = 10 ; magasság = 20 ; } @Override public void printCharacter () { System . ki . println ( "Szimbólum = " + szimbólum + " Szélesség = " + szélesség + " Magasság = " + magasság ); } } public class CharacterB kiterjeszti EnglishCharacter { public KarakterB (){ szimbólum = 'B' ; szélesség = 20 ; magasság = 30 ; } @Override public void printCharacter () { System . ki . println ( "Szimbólum = " + szimbólum + " Szélesség = " + szélesség + " Magasság = " + magasság ); } } public class CharacterC kiterjeszti EnglishCharacter { public CharacterC (){ szimbólum = 'C' ; szélesség = 40 ; magasság = 50 ; } @Override public void printCharacter () { System . ki . println ( "Szimbólum = " + szimbólum + " Szélesség = " + szélesség + " Magasság = " + magasság ); } } public class FlyweightFactory { privát HashMap < Integer , English Character > karakterek = new HashMap (); public EnglishCharacter getCharacter ( int characterCode ){ English Character character = karakterek . get ( characterCode ); if ( karakter == null ){ switch ( karakterKód ){ case 1 : { karakter = new CharacterA (); szünet ; } eset 2 : { karakter = new KarakterB (); szünet ; } eset 3 : { karakter = new CharacterC (); szünet ; } } karakterek . put ( karakterKód , karakter ); } return karakter ; } } /* * Egy osztály, amely bemutatja a Flyweight tervezési minta működését. * */ nyilvános osztály jelentkezés { public static void main ( String [] args ){ FlyweightFactory factory = new FlyweightFactory (); int [] karakterKódok = { 1 , 2 , 3 }; for ( int nextCode : characterCodes ){ EnglishCharacter character = gyári . getCharacter ( nextCode ); karakter . printCharacter (); } } }

Példa C#-ban

Forrásszöveg C# nyelven a rendszer használatával ; a System.Collections használatával ; névtér Flyweight { class MainApp { static void Main () { // Dokumentum létrehozása szöveges karakterlánccal document = "AAZZBBZB" ; char [] chars = dokumentum . ToCharArray (); CharacterFactory f = new CharacterFactory (); // külső állapot int pointSize = 10 ; // Minden karakterhez használj egy flyweight objektumot foreach ( char c in chars ) { pointSize ++; Karakter karakter = f . GetCharacter ( c ); karakter . Kijelző ( pointSize ); } // Várja meg a felhasználói konzolt . olvasni (); } } // "FlyweightFactory" class CharacterFactory { private Hashtable karakterek = new Hashtable (); public Karakter GetCharacter ( char key ) { // "Lusta inicializálást" használ Karakter karakter = karakterek [ kulcs ] karakterként ; if ( karakter == null ) { switch ( key ) { case 'A' : karakter = new KarakterA (); szünet ; eset 'B' : karakter = új KarakterB (); szünet ; //... eset 'Z' : karakter = új KarakterZ (); szünet ; } karakter . Add ( kulcs , karakter ); } return karakter ; } } // "légysúly" absztrakt osztály Karakter { védett karakter szimbólum ; védett in szélesség ; védett belmagasság ; _ védett int emelkedés ; védett int ereszkedés ; védett int pointSize ; public virtual void Megjelenítés ( int pointSize ) { this . pointSize = pointSize ; Konzol . WriteLine ( ez . szimbólum + " (pontméret " + ez . pointSize + ")" ); } } "ConcreteFlyweight" class CharacterA : Character { // Constructor public CharacterA () { this . szimbólum = 'A' ; ezt . magasság = 100 ; ezt . szélesség = 120 ; ezt . emelkedés = 70 ; ezt . ereszkedés = 0 ; } } "ConcreteFlyweight" class KarakterB : Karakter { // Constructor public CharacterB () { this . szimbólum = 'B' ; ezt . magasság = 100 ; ezt . szélesség = 140 ; ezt . emelkedés = 72 ; ezt . ereszkedés = 0 ; } } // ... C, D, E stb. "ConcreteFlyweight" class CharacterZ : Karakter { // Konstruktor public CharacterZ () { this . szimbólum = 'Z' ; ezt . magasság = 100 ; ezt . szélesség = 100 ; ezt . emelkedés = 68 ; ezt . ereszkedés = 0 ; } } }

C++ példa

Forrásszöveg C++ nyelven #include <térkép> #include <iostream> #include <memória> // "Légysúly" osztály Karakter { nyilvános : virtual ~ Karakter () = alapértelmezett ; virtuális üres kijelző () const = 0 ; védett : char mSymbol ; int mWidth ; int mMagasság ; int mascent ; int mDescent ; int mPointSize ; }; // "ConcreteFlyweight" osztály ConcreteCharacter : nyilvános karakter { nyilvános : // Constructor ConcreteCharacter ( char aSymbol , int aPointSize ) { mSymbol = aSzimbólum ; m Szélesség = 120 ; mMagasság = 100 ; mascent = 70 ; mDescent = 0 ; mPointSize = aPointSize ; } // from Character virtual void display () const { std :: cout << mSymbol << " ( PontSize " << mPointSize << " ) \n " ; } }; // "FlyweightFactory" sablon < const int POINT_SIZE > osztályú CharacterFactory { nyilvános : const Character & getCharacter ( char aKey ) { // "Lusta inicializálást" használ Karakterek :: const_iterator it = mCharacters . megtalálni ( aKey ); if ( mCharacters . end ( ) == it ) { mKarakterek [ aKey ] = std :: make_unique < const ConcreteCharacter > ( aKey , POINT_SIZE ); return * mCharacters [ aKey ]; } másik { return * it -> second ; } } privát : a karakterek használatával = std :: map < char , std :: egyedi_ptr < const Karakter > > ; Karakterek mKarakterek ; }; int main (){ std :: stringdocument = " AAZZBBZB " ; CharacterFactory < 12 > characterFactory ; for ( auto it : document ){ auto && karakter = karakterFactory . getCharacter ( it ); karakter . kijelző (); } return 0 ; }

PHP5 példa

PHP forráskód <?php // "FlyweightFactory" class CharacterFactory { private $characters = array (); public function GetCharacter ( $kulcs ) { // A "lusta inicializálást" használja if ( ! array_key_exists ( $kulcs , $this -> karakterek )) { switch ( $key ) { case 'A' : $this -> karakterek [ $kulcs ] = új karakterA (); szünet ; eset 'B' : $this -> karakterek [ $kulcs ] = új KarakterB (); szünet ; //... 'Z' eset : $this -> karakterek [ $key ] = new CharacterZ (); szünet ; } } return $this -> karakterek [ $kulcs ]; } } // "Flyweight" absztrakt class Character { protected $symbol ; védett $szélesség ; védett $magasság ; védett $emelkedés ; védett $származás ; védett $pointSize ; public abstract function Megjelenítés ( $pointSize ); } "ConcreteFlyweight" class KarakterA kiterjeszti Karakter { // Konstruktor public function __construct () { $this -> symbol = 'A' ; $ez -> magasság = 100 ; $ez -> szélesség = 120 ; $ez -> emelkedés = 70 ; $ez -> ereszkedés = 0 ; } public function Megjelenítés ( $pointSize ) { $this -> pointSize = $pointSize ; print ( $this -> symbol . " (pointsize " . $this -> pointSize . ")" ); } } "ConcreteFlyweight" class KarakterB kiterjeszti Karakter { // Konstruktor public function __construct () { $this -> symbol = 'B' ; $ez -> magasság = 100 ; $ez -> szélesség = 140 ; $ez -> emelkedés = 72 ; $ez -> ereszkedés = 0 ; } public function Megjelenítés ( $pointSize ) { $this -> pointSize = $pointSize ; print ( $this -> symbol . " (pointsize " . $this -> pointSize . ")" ); } } // ... C, D, E stb. "ConcreteFlyweight" class CharacterZ extends Karakter { // Konstruktor public function __construct () { $this -> symbol = 'Z' ; $ez -> magasság = 100 ; $ez -> szélesség = 100 ; $ez -> emelkedés = 68 ; $ez -> ereszkedés = 0 ; } public function Megjelenítés ( $pointSize ) { $this -> pointSize = $pointSize ; print ( $this -> symbol . " (pointsize " . $this -> pointSize . ")" ); } } $document = "AAZZBBZB" ; // Dokumentum készítése szöveggel $chars = str_split ( $document ); print_r ( $karakterek ); $f = new CharacterFactory (); // külső állapot $pointSize = 0 ; // Minden karakterhez használj egy flyweight objektumot foreach ( $chars mint $key ) { $pointSize ++ ; $karakter = $f -> GetCharacter ( $kulcs ); $karakter -> Kijelző ( $pointSize ); } ?>

VB.NET példa

Forráskód a VB.NET-ben Import System.Collections Névtér Flyweight Osztály Program Megosztott al - () ' Dokumentum létrehozása szöveggel Dim document As String = "AAZZBBZB" Dim chars As Char () = dokumentum . ToCharArray () Dim f , mint új karaktergyár () ' külső állapot Dim point Size As Integer = 10 ' Minden karakterhez használjon egy flyweight objektumot Minden c As Char In chars pointSize + = 1 Dim karakter As Character = f . GetCharacter ( c ) karakter . Kijelző ( pointSize ) Következő Várja meg a felhasználói konzolt . Olvassa el () End Sub End Class "FlyweightFactory" Class CharacterFactory Privát karakterek új hashtableként ( ) Nyilvános függvény GetCharacter ( ByVal gomb As Char ) As Character ' "Lusta inicializálást" használ. Halvány karakter As Character = TryCast ( karakterek ( billentyű ), Karakter ) Ha a karakter semmi , akkor válassza a Kis- és nagybetűbillentyűket Kis- és nagybetűk "A"c karakter = Új karakterA () Kilépés Kiválasztás Kis- és nagybetű "B"c karakter = Új karakterB () Kilépés Kiválasztás '... Kis- és nagybetű "Z"c karakter = Új karakterZ () Kilépés Kiválasztás Vége Karakterek kiválasztása . Add ( gomb , karakter ) End If Return karakter End Function End Class ' "Flyweight" MustInherit Class Karakter Védett szimbólum As Char Védett szélesség As Integer Védett magasság Egész Szám Védett emelkedés Egész Szám Védett süllyedés Egész Szám Védett pont Méret As Integer Public MustOverride Sub Display ( ByVal pointSize As Integer ) Végosztály _ ' "ConcreteFlyweight" Class CharacterA örökli a karaktert ' Constructor Public Sub New () Me . szimbólum = "A" c Me . magasság = 100 Me . szélesség = 120 Me . emelkedés = 70 Me . ereszkedés = 0 End Sub Nyilvános felülbírálja az almegjelenítést ( ByVal pointSize As Integer ) Me . pointSize = pointSize konzol . WriteLine ( Me . symbol & " ( pontméret " & Me . pointSize & " ) " ) End Sub End Class ' "ConcreteFlyweight" osztály Karakter B örökli a karaktert ' Konstruktor Nyilvános al Új () Me . szimbólum = "B" c Me . magasság = 100 Me . szélesség = 140 Me . emelkedés = 72 Me . ereszkedés = 0 End Sub Nyilvános felülbírálja az almegjelenítést ( ByVal pointSize As Integer ) Me . pointSize = pointSize konzol . WriteLine ( Me . symbol & " ( pointsize " & Me . pointSize & " )" ) End Sub végi osztály ' ... C, D, E stb. ' "ConcreteFlyweight" Class CharacterZ Inherits Character ' Constructor Public Sub New () Me . szimbólum = "Z" c Me . magasság = 100 Me . szélesség = 100 Me . emelkedés = 68 Me . ereszkedés = 0 End Sub Nyilvános felülbírálja az almegjelenítést ( ByVal pointSize As Integer ) Me . pointSize = pointSize konzol . WriteLine ( Me . symbol & " ( pontméret " & Me . pointSize & " ) " ) End Sub End Class End Namespace

Ruby példa

Ruby forráskód # Létesítményobjektum osztály Lámpa attr_reader :color A #attr_reader a color attribútumot #az osztályon kívül is elérhetővé teszi a .color meghívásával egy lámpa példányon def inicializálás ( szín ) @ szín = szín vége osztály TreeBranch def inicializálás ( ág_szám ) @ág_szám = ág_szám vége def hang ( lámpa ) a "Hang #{ lamp . color } lámpát a #{ @branch_number } ágra helyezi " end end # Flyweight Factory Class LampFactory def inicialize @lamps = {} end def find_lamp ( color ) if @lámpák . van_kulcs? ( color ) # ha a lámpa már létezik, hivatkozzon rá ahelyett, hogy új lámpát hozna létre = @lámpák [ szín ] else lámpa = Lámpa . new ( color ) @lamps [ color ] = lámpavég lámpavég _ _ def lámpák_összes_száma @lámpák . méret vége vége class ChristmasTree def inicialize @lamp_factory = Lámpagyár . új @lamps_hung = 0 öltöztesd fel_a_favéget def hang_lamp ( szín , ág_szám ) TreeBranch . új ( ág_száma ) . hang ( @lámpa_gyár . find_lamp ( color )) @lamps_hung += 1 end def dress_up_the_tree hang_lamp ( 'piros' , 1 ) hang_lamp ( 'kék' , 1 ) hang_lamp ( 'sárga' , 1 ) hang_lamp ( 'piros' , 2 ) hang_lamp ( 'kék' , 2 ) hang_lamp ( ' 2 sárga ) ' hang_lamp ( 'piros' , 3 ) hang_lamp ( 'kék' , 3 ) hang_lamp ( 'sárga' , 3 ) hang_lamp ( 'piros' , 4 ) hang_lamp ( 'kék' , 4 ) hang_lamp ( 'sárga' , 4 ) hang_lamp ( 'sárga', 4) 'piros' , 5 ) hang_lamp ( 'kék' , 5 ) hang_lamp ( 'sárga' , 5 ) hang_lamp ( 'piros' , 6 ) hang_lamp ( 'kék' , 6 ) hang_lamp ( 'sárga' , 6 ) hang_lamp ( 'piros' ' , 7 ) hang_lamp ( 'kék' , 7 ) hang_lamp ( 'sárga' , 7 ) a "Made #{ @lamp_factory . total_number_of_lamps_made } total lamps" végét teszi

Szimbólumok a Smalltalkban

A Smalltalk karakterei szinte azonosak a "hétköznapi karakterláncokkal", de nem generálódnak minden alkalommal újra. Két azonos karakter valójában mindig a Symbol osztály azonos példánya, míg két azonos karakterlánc a String osztály különböző példányai lehetnek.

Linkek