Peso mosca (patrón de diseño)
La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la
versión revisada el 4 de julio de 2016; las comprobaciones requieren
23 ediciones .
Un peso mosca ( eng. flyweight , “lightweight (elemento)”) es un patrón de diseño estructural en el que un objeto que se presenta como una instancia única en diferentes lugares del programa, de hecho, no lo es.
Propósito
Optimización de la memoria al evitar la creación de instancias de elementos que tienen una entidad común.
Descripción
Flyweight se utiliza para reducir costos cuando se trata de una gran cantidad de objetos pequeños. Al diseñar un Flyweight, es necesario dividir sus propiedades en externas e internas. Las propiedades internas siempre permanecen sin cambios, mientras que las propiedades externas pueden diferir según el lugar y el contexto de aplicación y deben trasladarse fuera del instalador.
Flyweight complementa la plantilla de Factory Method de tal manera que cuando un cliente llama a un Factory Method para crear un nuevo objeto, busca un objeto ya creado con los mismos parámetros que el requerido y se lo devuelve al cliente. Si no existe tal objeto, la fábrica creará uno nuevo.
Ejemplos
Ejemplo de Python
Código fuente en Python
class Lámpara ( objeto ):
def __init__ ( self , color ):
self . color = color
clase LampFactory :
lámparas = dict ()
@staticmethod
def get_lamp ( color ):
devuelve LampFactory . lámparas _ setdefault ( color , Lámpara ( color ))
clase TreeBranch ( objeto ):
def __init__ ( self , branch_number ):
self . numero_sucursal = numero_sucursal
def colgar ( self , lámpara ):
print ( f "Colgar $ { lámpara . color } [$ { id ( lámpara ) } ] lámpara en rama $ { self . branch_number } [$ { id ( self ) } ]" )
clase ChristmasTree ( objeto ):
def __init__ ( self ):
self . lámparas_colgadas = 0
self . ramas = {}
def get_branch ( self , número ):
return self . ramas _ setdefault ( número , TreeBranch ( número ))
def vestir_el_árbol ( self ):
self . hang_lamp ( "rojo" , 1 )
self . hang_lamp ( "azul" , 1 )
self . hang_lamp ( "amarillo" , 1 )
self . hang_lamp ( "rojo" , 2 )
self . hang_lamp ( "azul" , 2 )
self . hang_lamp ( "amarillo" , 2 )
self . hang_lamp ( "rojo" , 3 )
self . hang_lamp ( "azul" , 3 )
self . hang_lamp ( "amarillo" , 3 )
self . hang_lamp ( "rojo" , 4 )
self . hang_lamp ( "azul" , 4 )
self . hang_lamp ( "amarillo" , 4 )
self . hang_lamp ( "rojo" , 5 )
self . hang_lamp ( "azul" , 5 )
self . hang_lamp ( "amarillo" , 5 )
self . hang_lamp ( "rojo" , 6 )
self . hang_lamp ( "azul" , 6 )
self . hang_lamp ( "amarillo" , 6 )
self . hang_lamp ( "rojo" , 7 )
self . hang_lamp ( "azul" , 7 )
self . hang_lamp ( "amarillo" , 7 )
def hang_lamp ( self , color , branch_number ):
self . get_branch ( número_sucursal ) . colgar ( LampFactory . get_lamp ( color ))
self . lámparas_colgadas += 1
if __name__ == '__main__' :
ChristmasTree () . vestir_el_arbol ()
Ejemplo de Python (con anulación del constructor)
Código fuente de Python (con anulación del constructor)
lámpara de clase ( objeto ):
__instances = dict ()
def __nuevo__ ( cls , color ):
devuelve cls . __instancias . setdefault ( color , super () . __nuevo__ ( cls ))
def __init__ ( auto , color ):
auto . color = color
clase TreeBranch ( objeto ):
def __init__ ( self , branch_number ):
self . numero_sucursal = numero_sucursal
def colgar ( self , lámpara ):
print ( f "Colgar $ { lámpara . color } [$ { id ( lámpara ) } ] lámpara en rama $ { self . branch_number } [$ { id ( self ) } ]" )
clase ChristmasTree ( objeto ):
def __init__ ( self ):
self . lámparas_colgadas = 0
self . ramas = {}
def get_branch ( self , número ):
return self . ramas _ setdefault ( número , TreeBranch ( número ))
def vestir_el_árbol ( self ):
para rama en rango ( 1 , 8 ):
para color en "rojo" , "azul" , "amarillo" :
self . hang_lamp ( color , rama )
def hang_lamp ( self , color , branch_number ):
self . get_branch ( número_sucursal ) . colgar ( Lámpara ( color ))
uno mismo . lámparas_colgadas += 1
if __name__ == '__main__' :
ChristmasTree () . vestir_el_arbol ()
Ejemplo #1 en Java
Fuente Java
importar java.util.* ;
enumeración pública FontEffect {
NEGRITA , CURSIVA , SUPERSCRIPT , SUBSCRIPT , TACHADO
}
public final class FontData {
/**
* Un mapa hash débil eliminará las referencias no utilizadas a FontData.
* Los valores deben estar envueltos en WeakReferences,
* porque los objetos de valor en el mapa hash débil están sujetos a referencias fuertes.
*/
private static final WeakHashMap < FontData , WeakReference < FontData >> flyweightData =
new WeakHashMap < FontData , WeakReference < FontData >> ();
Tamaño del punto int final privado ; cara de fuente de cadena final privada ; color final privado color ; conjunto final privado < FontEffect > efectos ;
private FontData ( int pointSize , String fontFace , Color color , EnumSet < FontEffect > efectos ) {
this . tamañopunto = tamañopunto ;
esto _ cara de fuente = cara de fuente ;
esto _ color = color ;
esto _ efectos = Colecciones . unmodificableSet ( efectos );
}
Public static FontData create ( int pointSize , String fontFace , Color color ,
FontEffect ... efectos ) {
EnumSet < FontEffect > EffectsSet = EnumSet . noneOf ( FontEffect . clase );
conjunto de efectos . addAll ( Arreglos . asList ( efectos ));
// No nos preocupamos por el costo de creación de objetos, estamos reduciendo el consumo total de memoria
FontData data = new FontData ( pointSize , fontFace , color , effectsSet );
if ( ! flyweightData . containsKey ( data )) {
flyweightData . put ( datos , nueva referencia débil < FontData > ( datos )); } // devuelve la única copia inmutable con los valores dados devuelve flyweightData . obtener ( datos ). obtener (); }
@Override
public boolean equals ( Object obj ) {
if ( obj instanceof FontData ) {
if ( obj == this ) {
return true ;
}
FontData otro = ( FontData ) obj ;
devolver otro . tamañopunto == tamañopunto && otro . cara de fuente . es igual a ( fontFace )
&& otro . color _ es igual a ( color ) && otro . efectos _ es igual ( efectos );
}
devuelve falso ;
}
@Override
public int hashCode () {
return ( tamaño del punto * 37 + efectos . hashCode () * 13 ) * fontFace . código hash ();
}
// Getters para los datos de fuente, pero no setters. FontData es inmutable.
}
Ejemplo #2 en Java
Fuente Java
clase pública abstracta _ _
símbolo de carácter protegido ;
ancho int protegido ;
altura int protegida ;
public abstract void printCharacter ();
}
public class CharacterA extiende EnglishCharacter {
carácter público A () {
símbolo = 'A' ;
ancho = 10 ;
altura = 20 ;
}
@Override
public void printCharacter () {
System . fuera _ println ( "Símbolo = " + símbolo + " Ancho = " + ancho + " Alto = " + alto );
}
}
public class CharacterB extiende EnglishCharacter {
carácter público B () {
símbolo = 'B' ;
ancho = 20 ;
altura = 30 ;
}
@Override
public void printCharacter () {
System . fuera _ println ( "Símbolo = " + símbolo + " Ancho = " + ancho + " Alto = " + alto );
}
}
public class CharacterC extiende EnglishCharacter {
carácter público C () {
símbolo = 'C' ;
ancho = 40 ;
altura = 50 ;
}
@Override
public void printCharacter () {
System . fuera _ println ( "Símbolo = " + símbolo + " Ancho = " + ancho + " Alto = " + alto );
}
}
public class FlyweightFactory {
private HashMap < Integer , EnglishCharacter > caracteres = new HashMap ();
public EnglishCharacter getCharacter ( int characterCode ){
EnglishCharacter character = caracteres . obtener ( código de carácter );
if ( carácter == nulo ){
cambiar ( código de carácter ){
caso 1 : {
carácter = nuevo CarácterA ();
romper ;
}
caso 2 : {
carácter = nuevo CarácterB ();
romper ;
}
caso 3 : {
carácter = nuevo CarácterC ();
romper ;
}
}
caracteres . poner ( código de carácter , carácter );
}
carácter de retorno ; }
}
/*
* Una clase que muestra cómo funciona el patrón de diseño Flyweight.
* */
Aplicación de clase pública {
public static void main ( String [] args ){
FlyweightFactory factory = new FlyweightFactory ();
int [] códigos de carácter = { 1 , 2 , 3 };
for ( int nextCode : characterCodes ){
EnglishCharacter character = factory . getCharacter ( siguienteCodigo );
personaje _ imprimirCaracter ();
}
}
}
Ejemplo en C#
Texto fuente en C#
utilizando el sistema ;
utilizando System.Collections ;
espacio de nombres peso mosca
{
class MainApp
{
static void Main ()
{
// Crea un documento con la
cadena de texto document = "AAZZBBZB" ;
char [] chars = documento . ToCharArray ();
Fábrica de Personajes f = nueva Fábrica de Personajes ();
// estado extrínseco
int pointSize = 10 ;
// Para cada carácter use un objeto
flyweight foreach ( char c in chars )
{
pointSize ++;
Carácter carácter = f . ObtenerCarácter ( c );
personaje _ Pantalla ( tamaño de punto );
}
// Esperar a la
Consola del usuario . leer ();
}
}
// "Fábrica de Peso Mosca"
class CharacterFactory
{
caracteres privados de Hashtable = new Hashtable ();
public Character GetCharacter ( char key )
{
// Usa "lazy initialization"
Carácter character = caracteres [ clave ] como Carácter ;
if ( carácter == nulo )
{
cambiar ( tecla )
{
caso 'A' : carácter = nuevo CarácterA (); romper ;
caso 'B' : carácter = nuevo CarácterB (); romper ;
//...
case 'Z' : carácter = nuevo CarácterZ (); romper ;
}
caracteres . Añadir ( clave , carácter );
}
carácter de retorno ; } }
// "peso mosca"
carácter de clase abstracta { símbolo de carácter protegido ; ancho int protegido ; altura int protegida ; ascenso int protegido ; descenso int protegido ; tamaño del punto int protegido ;
Visualización de vacío virtual público ( int pointSize ) { this . tamañopunto = tamañopunto ; consola _ WriteLine ( este . símbolo + " (tamaño de punto " + este . tamaño de punto + ")" ); } }
// "Peso mosca de hormigón"
class CharacterA : Character
{
// Constructor
public CharacterA ()
{
this . símbolo = 'A' ;
esto _ altura = 100 ;
esto _ ancho = 120 ;
esto _ ascender = 70 ;
esto _ descenso = 0 ;
}
}
// "Peso mosca de hormigón"
class CharacterB : Character
{
// Constructor
public CharacterB ()
{
this . símbolo = 'B' ;
esto _ altura = 100 ;
esto _ ancho = 140 ;
esto _ ascender = 72 ;
esto _ descenso = 0 ;
}
}
// ... C, D, E, etc.
// "Peso mosca de hormigón"
class CharacterZ : Character
{
// Constructor
public CharacterZ ()
{
this . símbolo = 'Z' ;
esto _ altura = 100 ;
esto _ ancho = 100 ;
esto _ ascender = 68 ;
esto _ descenso = 0 ;
}
}
}
Ejemplo de C++
Texto fuente en C++
#incluir <mapa>
#incluir <iostream>
#include <memoria>
// Carácter de clase "Peso mosca"
{
público :
~ Carácter virtual () = predeterminado ;
visualización de vacío virtual () const = 0 ;
protegido :
char mSímbolo ;
int mAncho ;
int mAltura ;
int mAascenso ;
int mDescenso ;
int mTamañoPunto ;
};
// Clase "ConcreteFlyweight" ConcreteCharacter : carácter público
{
público :
// Constructor
ConcreteCharacter ( char aSymbol , int aPointSize )
{
mSímbolo = aSímbolo ;
mAncho = 120 ;
mAltura = 100 ;
mAascenso = 70 ;
mDescenso = 0 ;
mTamañoPunto = aTamañoPunto ;
}
// de Carácter
virtual void display () const {
std :: cout << mSymbol << " (TamañoPunto " << mTamañoPunto << " ) \n " ;
}
};
// plantilla "FlyweightFactory" < const int POINT_SIZE >
clase CharacterFactory
{
público :
const Carácter & getCharacter ( char aKey )
{
// Utiliza caracteres de "inicialización diferida
" :: const_iterator it = mCharacters . encontrar ( unaClave );
if ( mCaracteres . end () == it ) {
mCharacters [ aKey ] = std :: make_unique < const ConcreteCharacter > ( aKey , POINT_SIZE );
return * mCaracteres [ unaClave ];
} más {
volver * it -> segundo ;
}
}
privado :
usando Caracteres = std :: map < char , std :: unique_ptr < const Character > > ;
Caracteres mCaracteres ;
};
int principal (){
std :: stringdocument = " AAZZBBZB " ;
Fábrica de personajes < 12 > Fábrica de personajes ;
para ( automático : documento ) {
auto && carácter = characterFactory . getCharacter ( eso );
personaje _ mostrar ();
}
devolver 0 ;
}
Ejemplo de PHP5
codigo fuente php
<?php
// "FlyweightFactory"
class CharacterFactory
{
private $caracteres = array ();
public function GetCharacter ( $key )
{
// Usa "inicialización diferida"
if ( ! array_key_exists ( $key , $this -> caracteres ))
{
switch ( $key )
{
case 'A' : $this -> caracteres [ $key ] = nuevo CarácterA (); romper ;
case 'B' : $this -> caracteres [ $key ] = new CharacterB (); romper ;
//...
case 'Z' : $this -> caracteres [ $clave ] = new CharacterZ (); romper ;
}
}
devuelve $esto -> caracteres [ $clave ];
}
}
// Clase abstracta "Peso mosca" Carácter { protected $símbolo ; protegido $ ancho ; altura protegida $ ; $ascenso protegido ; $descendencia protegida ; protegido $ tamaño del punto ;
Visualización de la función abstracta pública ( $pointSize ); }
// "Peso mosca de hormigón"
class CharacterA extends Character
{
// Constructor
public function __construct ()
{
$this -> símbolo = 'A' ;
$esto -> altura = 100 ;
$esto -> ancho = 120 ;
$esto -> ascenso = 70 ;
$este -> descenso = 0 ;
}
public function Mostrar ( $pointSize )
{
$this -> pointSize = $pointSize ;
print ( $este -> símbolo . " (tamaño del punto " . $este -> tamaño del punto . ")" );
}
}
// "Peso mosca de hormigón"
class CharacterB extends Character
{
// Constructor
public function __construct ()
{
$this -> símbolo = 'B' ;
$esto -> altura = 100 ;
$esto -> ancho = 140 ;
$esto -> ascenso = 72 ;
$este -> descenso = 0 ;
}
public function Mostrar ( $pointSize )
{
$this -> pointSize = $pointSize ;
print ( $este -> símbolo . " (tamaño del punto " . $este -> tamaño del punto . ")" );
}
}
// ... C, D, E, etc.
// "Peso mosca de hormigón"
class CharacterZ extends Character
{
// Constructor
public function __construct ()
{
$this -> símbolo = 'Z' ;
$esto -> altura = 100 ;
$esto -> ancho = 100 ;
$esto -> ascenso = 68 ;
$este -> descenso = 0 ;
}
public function Mostrar ( $pointSize )
{
$this -> pointSize = $pointSize ;
print ( $este -> símbolo . " (tamaño del punto " . $este -> tamaño del punto . ")" );
}
}
$documento = "AAZZBBZB" ;
// Crea un documento con texto
$chars = str_split ( $documento );
print_r ( $caracteres );
$f = nueva Fábrica de Personajes ();
// estado extrínseco
$pointSize = 0 ;
// Para cada carácter use un objeto
flyweight foreach ( $chars as $key ) {
$pointSize ++ ;
$carácter = $f -> ObtenerCarácter ( $clave );
$carácter -> Mostrar ( $puntoTamaño );
}
?>
Código fuente en VB.NET
Sistema de Importaciones.Cobranzas
Peso mosca del espacio de nombres
Class Program
Shared Sub Main ()
' Construye un documento con texto
Dim document As String = "AAZZBBZB"
Dim chars As Char () = document . ToCharArray ()
Dim f Como nuevo CharacterFactory ()
' estado extrínseco
Dim pointSize As Integer = 10
' Para cada carácter, use un objeto de peso ligero
Para cada c As Char In chars
pointSize += 1
Dim character As Character = f . GetCharacter ( c )
carácter . Mostrar ( tamaño de punto )
Siguiente
'Esperar a la
Consola del usuario . Lectura ()
End Sub
End Class
' "FlyweightFactory"
Class CharacterFactory Personajes
privados como nueva tabla hash ()
Función pública GetCharacter ( tecla ByVal As Char ) As Character ' Usa "inicialización diferida" Dim character As Character = TryCast ( caracteres ( key ), Character ) Si el carácter no es nada , seleccione Case key Case " A "c character = New CharacterA () Salir Seleccionar Caso "B"c carácter = Nuevo CarácterB () Salir Seleccionar '... Caso "Z"c carácter = Nuevo CarácterZ () Salir Seleccionar Finalizar Seleccionar caracteres . Añadir ( tecla , carácter ) Finalizar si Retornar carácter Finalizar función Finalizar clase
' "Peso ligero"
MustInherit Class Carácter
Símbolo protegido As Char Ancho protegido As Integer Altura protegida As Integer Ascenso protegido As Integer Descenso protegido As Integer Tamaño de punto protegido As Integer
Public MustOverride Sub Display ( ByVal pointSize As Integer )
End Class
' "ConcreteFlyweight"
Class CharacterA
Hereda Character
' Constructor
Public Sub New ()
Me . símbolo = "A" c
Yo . altura = 100
Me . ancho = 120
Me . ascenso = 70
Me . descenso = 0
End Sub
Public Overrides Sub Display ( ByVal pointSize As Integer )
Me . tamañopunto = tamañopunto
Consola . WriteLine ( Me . símbolo & " (tamaño de punto " & Me . tamaño de punto & ")" )
End Sub
End Class
' "ConcreteFlyweight"
Class CharacterB
Hereda Character
' Constructor
Public Sub New ()
Me . símbolo = "B" c
Yo . altura = 100
Me . ancho = 140
Me . ascenso = 72
Yo . descenso = 0
End Sub
Public Overrides Sub Display ( ByVal pointSize As Integer )
Me . tamañopunto = tamañopunto
Consola . WriteLine ( Me . símbolo & " (tamaño de punto " & Me . tamaño de punto & ")" )
End Sub
clase final
'... C, D, E, etc.
' "ConcreteFlyweight"
Class CharacterZ
Hereda Character
' Constructor
Public Sub New ()
Me . símbolo = "Z" c
Yo . altura = 100
Me . ancho = 100
Me . ascenso = 68
Yo . descenso = 0
End Sub
Public Overrides Sub Display ( ByVal pointSize As Integer )
Me . tamañopunto = tamañopunto
Consola . WriteLine ( Me . símbolo & " (tamaño de punto " & Me . tamaño de punto & ")" )
End Sub
End Class
End Namespace
código fuente rubí
#
Clase de objeto de instalación Lamp
attr_reader :color
#attr_reader hace que el atributo de color esté disponible fuera
#de la clase llamando a .color en una instancia de Lamp
def inicializar ( color )
@color = color
final
final
clase TreeBranch
def initialize ( branch_number )
@branch_number = branch_number
end
def hang ( lámpara )
pone "Colgar #{ lámpara . color } lámpara en la rama #{ @branch_number } "
end
end
# Flyweight Factory
class LampFactory
def initialize
@lamps = {}
end
def find_lamp ( color )
si @lamps . tiene_clave? ( color )
# si la lámpara ya existe, haga referencia a ella en lugar de crear una nueva
lámpara = @lámparas [ color ]
más
lámpara = Lámpara . nuevo ( color )
@lamps [ color ] = final de lámpara
final de
lámpara
def total_number_of_lamps_made
@lamps . tamaño
final
final
class ChristmasTree
def initialize
@lamp_factory = LampFactory . nuevo
@lamps_hung = 0
dress_up_the_tree
final
def hang_lamp ( color , branch_number )
TreeBranch . nuevo ( número_sucursal ) . colgar ( @lamp_factory . find_lamp ( color ))
@lamps_hung += 1
final
def vestir_el_árbol
lámpara_colgar ( 'rojo' , 1 )
lámpara_colgar ( 'azul' , 1 )
lámpara_colgar ( 'amarillo' , 1 )
lámpara_colgar ( 'rojo' , 2 )
lámpara_colgar ( 'azul' , 2 )
lámpara_colgar ( 'amarillo' , 2 )
lámpara_colgar ( 'rojo' , 3 )
lámpara_colgar ( 'azul' , 3 )
lámpara_colgar ( 'amarillo' , 3 )
lámpara_colgar ( 'rojo' , 4 )
lámpara_colgar ( 'azul' , 4 )
lámpara_colgar ( 'amarillo' , 4 )
lámpara_colgar ( 'rojo' , 5 )
lámpara_colgar ( 'azul' , 5 )
lámpara_colgar ( 'amarillo' , 5 )
lámpara_colgar ( 'rojo' , 6 )
lámpara_colgar ( 'azul' , 6 )
lámpara_colgar ( 'amarillo' , 6 )
lámpara_colgar ( 'rojo' ' , 7 )
lámpara_colgada ( 'azul' , 7 )
lámpara_colgada ( 'amarillo' , 7 )
pone "Hecho #{ @lamp_factory . número_total_de_lámparas_hechas } total de lámparas"
end
end
Los caracteres en Smalltalk son casi idénticos a las "cadenas ordinarias", pero no se regeneran cada vez. De hecho, dos caracteres idénticos son siempre la misma instancia de la clase Símbolo, mientras que dos cadenas idénticas pueden ser instancias diferentes de la clase Cadena.
Enlaces