Analysis of Android source code design patterns and practices (22nd)
Chapter 2. metadata sharing
The metadata mode is one of the structural design modes and is an implementation of the Object pool. Share objects like their names to avoid repeated creation. Our commonStringThe shared mode is used, soStringThe type object cannot be changed after it is created.StringJVM only creates oneStringObjects correspond to these two different object references.
1. Definition
Use one share to avoid overhead of a large number of objects with the same content. The metadata mode can effectively support a large number of fine-grained objects.
2. Use Cases
(1) A large number of similar objects exist in the system.
(2) fine-grained objects all have close external states, and the internal state is not related to the environment, that is, the object has no specific identity.
(3) scenarios requiring buffer pools.
PS: Internal State and external State: the internal state of a shared object that does not change with the environment, A State that cannot be shared is called an external state.
3. UML class diagram
The metadata-sharing mode is a compound metadata-sharing mode.
(1)Flyweight: Abstract base class or interface of the object.
(2)ConcreateFlyweight: A specific metadata object. If the object has an internal state, it must provide storage space for the internal state.
(3)UnsharadConcreateFlyweight: The Objects represented by the composite metadata role cannot be shared, and can be decomposed into multiple combinations of simple metadata objects. This option is not available in the simple metadata mode, which is also the structural difference between the two.
(4)FlyweightFactoiy: The metadata factory is responsible for managing the metadata Object pool and creating metadata objects.
(5)Client: Maintain reference to all the metadata objects, and store the corresponding external status.
4. Simple implementation
Scenario: when buying a train ticket for the Chinese New Year, we need to query the ticket information. If a result is created every time a ticket is queried, a large number of repeated objects are created, they are frequently destroyed, making GC tasks heavy. In this case, we can use the metadata mode to cache these objects. The cache is used first during queries, and the cache is not re-created.
The first is the Ticket interface (Flyweight ):
public interface Ticket { public void showTicketInfo(String bunk);}
TrainTicket implementation class (ConcreateFlyweight ):
// Public class TrainTicket implements Ticket {public String from; // public String to; // public String bunk; // public int price; // price public TrainTicket (String from, String to) {this. from = from; this. to = to;} @ Override public void showTicketInfo (String bunk) {price = new Random (). nextInt (300); System. out. println ("purchase from" + from + "to" + to + "" + bunk + "train ticket" + ", price:" + price );}}
TicketFactory manage and query train tickets (FlyweightFactoiy ):
Public class TicketFactory {static Map
STicketMap = new ConcurrentHashMap
(); Public static Ticket getTicket (String from, String to) {String key = from + "-" + to; if (sTicketMap. containsKey (key) {System. out. println ("Using Cache ==>" + key); return sTicketMap. get (key);} else {System. out. println ("create object =>" + key); Ticket ticket = new TrainTicket (from, to); sTicketMap. put (key, ticket); return ticket ;}}}
Query:
Final class Client {public static void main (String [] args) {Ticket ticket01 = TicketFactory. getTicket ("Beijing", "Qingdao"); ticket01.showTicketInfo ("shangpu"); Ticket ticket02 = TicketFactory. getTicket ("Beijing", "Qingdao"); ticket02.showTicketInfo ("bottom shop"); Ticket ticket03 = TicketFactory. getTicket ("Beijing", "Xi'an"); ticket03.showTicketInfo ("ticket receipt ");}}
Result
Object To be created ==> Beijing-Qingdao purchases trains from Beijing to Qingdao, price: 71 use cache ==> Beijing-Qingdao purchases trains from Beijing to Qingdao, price: 32. Created object ==> Beijing-Xi'an: purchase a ticket from Beijing to Xi'an. Price: 246
5. Implementation in Android Source Code 1. Message
Because Android is event-drivenMessageA large numberMessageObject, causing problems such as high memory usage and frequent GC. SoMessageThe metadata mode is used.
MessagePassnextMember variables are reserved for the nextMessage, The last one is availableMessageOfnextIt is null. Thus formingMessage linked list.Message PoolYou can manage all idleMessage, OneMessageAfter use, you can userecycle()Method entryMessage PoolAnd passobtainStatic MethodMessage Pool.MessageAssume the responsibilities of the three elements in the metadata mode, that isFlyweightAbstract, andConcreateFlyweightRole, and at the same time assumeFlyweightFactoiyManage the responsibilities of the Object pool.
So we recommend obtain () to use Message. Do not use new.
// 1. Use new Message () // Message mess = new Message (); // 2. Use Message. obtain () Message mess = Message. obtain (); mess. what = 1; // Message mess = mHandler. obtainMessage (1); similar to the Code in the previous two lines, you can refer to the source code to view mHandler. sendMessage (mess );
6. Summary 1. Advantages
(1) greatly reduce the objects created by the application, reduce the memory usage of the program, and enhance the program performance.
(2) The metadata sharing mode allows shared objects in different environments.
2. Disadvantages
(1) make the system more complex. In order for objects to be shared, some States need to be externalized, which complicate the logic of the program.
(2) The metadata mode externalizes the state of the object to be shared, and reads the external State to slightly extend the running time.