Pregunta

Intent:

The intent of this pattern is to use sharing to support a large number of objects that have part of their internal state in common where the other part of state can vary.

Objects can share state via static fields.

What is the difference between sharing internal state of a large number of objects using the flyweight pattern and using static fields?

Is the pool of objects that the flyweight provides via its Factory what the flyweight is really all about?

¿Fue útil?

Solución

Using static fields, there can only ever be one instance of the object in use at any one point in time. Using the flyweight pattern, you can have any number of different instances in use simultaneously, (each one of which is used multiple times). The canonical example of the flyweight pattern is for a text editor, where you need an object instantiated for each and every character in the document. Instead of having one object in memory for each character in a 10,000 word document, you then only need 26 objects, (assuming document only uses lower case letters), one for the letter 'a', one for the letter 'b', etc., and they are reused, transiently, over and over again throughout the document, each time you need to perform some function or action requiring an 'a' object.

EDIT: to answer question from first comment below:
So, since you need 26 different objects, making a Letter class that was a static, or a singleton, wouldn't work. If it was a static, you can't make any instances, and so whatever the static values would have to be appropriate for every place in the code where you made use of it. If it was a singleton, then of course you only have one object. Every property would have to be adjustable (and adjusted) every time you used it. To use this pattern for the letters in the alphabet, you have to have 26 different classes, one for each letter...

Also, the "part of the class that can vary" really means that some fields represent state that is different for every instance of the class. Whereas the part that is in common means that the values of those common fields are in common for all uses of the object matching those state values (all the 'a's for example), not for every instance of the class.

Again, using the text editor as an example. Every place in your code that you need to deal with a character that is an 'a', you would first, go to the data structure that stores your 26 instances of character objects, and fetch the 'a' instance, You would first modify/change the varying properties (the properties not tied to it's nature as an 'a', but perhaps to it's font size, position, color, etc.) to match the needs for this specific character 'a' in the document.
Then you would utilize the object to do whatever it is you need to do with it, and then return it to the storage structure for reuse the next time your code needs an 'a'.

Otros consejos

The Flyweight pattern is used to avoid the overhead of large numbers of very similar classes. There are cases in programming where it seems that you need to generate a very large number of small class instances to represent data. Sometimes you can greatly reduce the number of different classes that you need to instantiate if you can recognize that the instances are fundamentally the same except for a few parameters. If you can move those variables outside the class instance and pass them in as part of a method call, the number of separate instances can be greatly reduced by sharing them.

In this context, it's important to bear in mind that the Flyweight was invented in an era where C# was nothing more than a rough sketch on some power point charts. And the maturation of the language was informed by some of these patterns implicitly. C# includes class members...

It is more typical to declare a non-static class with some static members, than to declare an entire class as static. Two common uses of static fields are to keep a count of the number of objects that have been instantiated, or to store a value that must be shared among all instances.

Source C# statics on MSDN

Taking things further, WPF technology popularized shared resources, and the result is often declarative code only.

So if your language of choice is C#, you may be advised to consider the Flyweight pattern against inherent properties that already exist in the language.

While patterns and their implementations are a bit subjective, using statics is a valid - albeit simplest possible - way to achieve Flyweight.

If you can use statics, that's great. Otherwise you can do something like you've touched on ... your factory that constructs flyweight objects can assign/reference the proper shared object.

Here is some example, it print all of the soldiers and their medals.

Because not all of the soldiers are decorated we are using the flyweight design pattern.

public class Soldiers
{
  private string[] _soldiers;
  private Dictionary<int, Medal> _medals = new Dictionary<int, Medal>();

  public Soldiers(string[] soldier)
  {
    this._soldiers = soldier;
  }

  public Medal this[int index]
  {
    get
    {
      Medal medal = new Medal();
      this._medals.Add(index, medal);
      return this._medals[index];
    }
  }

  public override string ToString()
  {
    var soldierList = new List<string>();
    for (var i = 0; i < this._soldiers.Length; i++)
    {
      string soldier = this._soldiers[i];
      if (this._medals.ContainsKey(i))
        soldier = soldier + ", Medal: " + this._medals.ElementAt(i).ToString();
      soldierList.Add(soldier);
    }
    return string.Join("; ", soldierList);
  }

  public class Medal
  {
    public bool Bronze;
    public bool Silver;
    public bool Gold;

    public override string ToString()
    {
      return (this.Bronze ? "Bronze," : "") + (this.Silver ? "Silver," : "") + (this.Gold ? "Gold" : "")
    }
  }
}

Usage:

Soldiers soldiers = new Soldiers(new string[] { "SoldierA" , "SoldierB" , "SoldierC" });

soldiers[0].Gold = true;
soldiers[0].Silver = true;
soldiers[2].Bronze = true;
Console.Write(soldiers.ToString()) // "SoldierA, Medal: Silver,Gold; SoldierB; SoldierC, Medal: Bronze";
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top