Flyweight definition:
Avoid the overhead of a large number of small classes with the same content (such as memory consumption), so that everyone can share a class (Meta class ).
Why?
The principle of object-oriented language is that everything is an object, but if it is used, sometimes the number of objects may appear very large. For example, if the word processing software uses every text as an object, there are thousands of words, and the number of objects is several thousand, which undoubtedly consumes memory. Therefore, we still need to "seek the same ground while reserving differences" to find out what these object groups have in common and design a metadata class, encapsulate classes that can be shared. In addition, some features depend on the application context and cannot be shared. In Flyweight, the two important concepts are internal states intrinsic and external States extrinsic.
To put it bluntly, we need to first create an original model and then generate a specific model with different characteristics in different scenarios and environments. Obviously, we need to generate different new objects here, therefore, the Factory mode is often used in the Flyweight mode. the internal state of Flyweight is used for sharing. Flyweight factory is responsible for maintaining a Flyweight pool (mode pool) to store internal State objects.
The Flyweight mode is a mode for improving program efficiency and performance, which greatly speeds up program running. there are many applications: for example, if you want to read a series of strings from a database and many of these strings are repeated, we can store these strings in the Flyweight pool.
How to use it?
Let's start with the Flyweight abstract interface:
Public interface Flyweightb
{
Public void operation (ExtrinsicState state );
}
// The abstract data type used in this mode (self-designed)
Public interface ExtrinsicState {}
The following figure shows the specific implementation of the interface (ConcreteFlyweight) and increases the memory space for the internal status. ConcreteFlyweight must be shareable and must be saved in any internal status (intrinsic). That is to say, concreteFlyweight must be independent of its application environment.
Public class ConcreteFlyweight implements Flyweight {
Private IntrinsicState state;
Public void operation (ExtrinsicState state)
{
// Specific operation
}
}
Of course, not all Flyweight implementation subclasses need to be shared, so there is another non-shared ConcreteFlyweight:
Public class UnsharedConcreteFlyweight implements Flyweight {
Public void operation (ExtrinsicState state ){}
}
Flyweight factory is responsible for maintaining a Flyweight pool (storing the internal status). When the client requests a shared Flyweight, the factory first searches whether the pool is applicable. If yes, factory simply returns and sends this object. Otherwise, it creates a new object, adds it to the pool, and then returns the object. pool
Public class FlyweightFactory {
// Flyweight pool
Private Hashtable flyweights = new Hashtable ();
Public Flyweight getFlyweight (Object key ){
Flyweight flyweight = (Flyweight) flyweights. get (key );
If (flyweight = null ){
// Generate a new ConcreteFlyweight
Flyweight = new ConcreteFlyweight ();
Flyweights. put (key, flyweight );
}
Return flyweight;
}
}
Now, the basic framework of the Flyweight mode is ready. Let's look at how to call it:
FlyweightFactory factory = new FlyweightFactory ();
Flyweight fly1 = factory. getFlyweight ("Fred ");
Flyweight fly2 = factory. getFlyweight ("Wilma ");
......
From the call point of view, it seems like a pure Factory use, but the secret lies in the internal design of the Factory.
The Flyweight mode is applied to XML and other data sources.
As we have mentioned above, when a large number of strings are read from the data source, there must be duplicates among them, we can use the Flyweight mode to improve efficiency. Take the recording CD as an example. In an XML file, stores multiple CD files.
Each CD has three fields:
1. Release date (year)
2. The Creator's name and other information (artist)
3. recording tracks (title)
The Creator's name may be repeated, that is, there may be multiple CDs of different tracks of the same artist in different periods. we use "creator name" as the shared ConcreteFlyweight. the other two fields are used as UnsharedConcreteFlyweight.
First, let's take a look at the content of the XML file of the Data source:
<? Xml version = "1.0"?>
<Collection>
<Cd>
<Title> Another Green World </title>
<Year> 1978 </year>
<Artist> Eno, Brian </artist>
</Cd>
<Cd>
<Title> Greatest Hits </title>
<Year> 1950 </year>
<Artist> Holiday, Billie </artist>
</Cd>
<Cd>
<Title> Taking Tiger Mountain (by strategy) </title>
<Year> 1977 </year>
<Artist> Eno, Brian </artist>
</Cd>
.......
</Collection>
Although there are only three CD examples in the above example, CD can be considered as a large number of repeated sub-classes, because there are only three fields in the example, and there are repeated (publisher name ).
CD is similar to the above interface Flyweight:
Public class CD {
Private String title;
Private int year;
Private Artist artist;
Public String getTitle () {return title ;}
Public int getYear () {return year ;}
Public Artist getArtist () {return artist ;}
Public void setTitle (String t) {title = t ;}
Public void setYear (int y) {year = y ;}
Public void setArtist (Artist a) {artist = ;}
}
Use "creator name" as the shared ConcreteFlyweight:
Public class Artist {
// The internal status is www.2cto.com.
Private String name;
// Note that Artist is immutable.
String getName () {return name ;}
Artist (String n ){
Name = n;
}
}
Let's take a look at the Flyweight factory, which is specifically used to make the above shareable ConcreteFlyweight: Artist
Public class ArtistFactory {
Hashtable pool = new Hashtable ();
Artist getArtist (String key ){
Artist result;
Result = (Artist) pool. get (key );
//// Generate a new Artist
If (result = null ){
Result = new Artist (key );
Pool. put (key, result );
}
Return result;
}
}
Author: tbwshc