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 .
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 );
}
?>
Forráskód a VB.NET-ben
Import System.Collections
Névtér Flyweight
Osztály Program
Megosztott al - fő ()
' 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 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
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