http://en.wikipedia.org/wiki/Flyweight_pattern

In computer programmingflyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects; it is a way to use objects in large numbers when a simple repeated representation would use an unacceptable amount of memory. Often some parts of the object state can be shared, and it is common practice to hold them in external data structures and pass them to the flyweight objects temporarily when they are used.

A classic example usage of the flyweight pattern is the data structures for graphical representation of characters in a word processor. It might be desirable to have, for each character in a document, a glyph object containing its font outline, font metrics, and other formatting data, but this would amount to hundreds or thousands of bytes for each character. Instead, for every character there might be a reference to a flyweight glyph object shared by every instance of the same character in the document; only the position of each character (in the document and/or the page) would need to be stored internally.

Another example is string interning.

In other contexts the idea of sharing identical data structures is called hash consing.

Immutability & Equality

To enable safe sharing, between clients and threads, Flyweight objects must be immutable. Flyweight objects are by definition value objects. The identity of the object instance is of no consequence therefore two Flyweight instances of the same value are considered equal.

Concurrency

Special consideration must be made in scenarios where Flyweight objects are created on multiple threads. If the list of values is finite and known in advance the Flyweights can be instantiated ahead of time and retrieved from a container on multiple threads with no contention. If Flyweights are instantiated on multiple threads there are two options:

  1. Make Flyweight instantiation single threaded thus introducing contention and ensuring one instance per value.
  2. Allow concurrent threads to create multiple Flyweight instances thus eliminating contention and allowing multiple instances per value. This option is only viable if the equality criterion is met.

History

According to a textbook Design Patterns: Elements of Reusable Object-Oriented Software,[1] the flyweight pattern was first coined and extensively explored byPaul Calder and Mark Linton in 1990[2] to efficiently handle glyph information in a WYSIWYG document editor, although similar techniques were already used in other systems, e.g., an application framework by Weinand et al. (1988).[3]

Example in Java

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
// Instances of CoffeeFlavour will be the Flyweights
class CoffeeFlavour {
  private final String name;
 
  CoffeeFlavour(String newFlavor) {
    this.name = newFlavor;
  }
 
  @Override
  public String toString() {
    return name;
  }
}
 
// Menu acts as a factory and cache for CoffeeFlavour flyweight objects
class Menu {
  private Map<String, CoffeeFlavour> flavours = new HashMap<String, CoffeeFlavour>();
 
  CoffeeFlavour lookup(String flavorName) {
    if (!flavours.containsKey(flavorName))
      flavours.put(flavorName, new CoffeeFlavour(flavorName));
    return flavours.get(flavorName);
  }
 
  int totalCoffeeFlavoursMade() {
    return flavours.size();
  }
}
 
class Order {
  private final int tableNumber;
  private final CoffeeFlavour flavour;
 
  Order(int tableNumber, CoffeeFlavour flavor) {
    this.tableNumber = tableNumber;
    this.flavour = flavor;
  }
 
  void serve() {
    System.out.println("Serving " + flavour + " to table " + tableNumber);
  }
}
 
class CoffeeShop {
  private final List<Order> orders = new ArrayList<Order>();
  private final Menu menu = new Menu();
 
  void takeOrder(String flavourName, int table) {
    CoffeeFlavour flavour = menu.lookup(flavourName);
    Order order = new Order(table, flavour);
    orders.add(order);
  }
 
  void service() {
    for (Order order : orders)
      order.serve();    
  }
 
  String report() {
    return "\ntotal CoffeeFlavour objects made: "
        + menu.totalCoffeeFlavoursMade();
  }
 
  public static void main(String[] args) {
    CoffeeShop shop = new CoffeeShop();
 
    shop.takeOrder("Cappuccino", 2);
    shop.takeOrder("Frappe", 1);
    shop.takeOrder("Espresso", 1);
    shop.takeOrder("Frappe", 897);
    shop.takeOrder("Cappuccino", 97);
    shop.takeOrder("Frappe", 3);
    shop.takeOrder("Espresso", 3);
    shop.takeOrder("Cappuccino", 3);
    shop.takeOrder("Espresso", 96);
    shop.takeOrder("Frappe", 552);
    shop.takeOrder("Cappuccino", 121);
    shop.takeOrder("Espresso", 121);
 
    shop.service();
    System.out.println(shop.report());
  }
}

 

 

 

posted on 2014-02-26 18:38  一天不进步,就是退步  阅读(451)  评论(0编辑  收藏  举报