Flyweight pattern vs static fields
Asked Answered
G

2

9

In my understanding the purpose of the flyweight pattern is to decrease memory footprint and increase performance by sharing common, extrinsic state. Why would anyone prefer to implement the pattern over storing the shared state in static fields?

Consider the following example: http://www.oodesign.com/flyweight-pattern-wargame-example-java-sourcecode.html

enter image description here

If I am right then the point in this example is to share the common state (soldierGraphicalRepresentation object) between all instances of the SoldierClient class by holding a reference to a single SoldierImp object.

Why would I hassle with implementing this design? I would be tempted to declare the SoldierClient class as follows:

public class SoldierClient implements Soldier 
{
    protected static Object soldierGraphicalRepresentation;
    private int currentLocationX;
    private int currentLocationY;

    static SoldierImp()
    {
        soldierGraphicalRepresentation = LoadGraphicalRepresentation();
    }

    public void moveSoldier(int previousLocationX, int previousLocationY, int newLocationX, int newLocationY) {
        // do stuff with the graphical representation

    }
}

This way all instances of the SoilderClient share a reference to the same soldierGraphicalRepresentation object and the same goal is achieved. Am I wrong?

Guilder answered 23/2, 2013 at 13:49 Comment(1)
Because you have several shared states? I'm not sure I understand the question. You might want to provide example code for what you mean.Melodiemelodion
M
12

The point of the pattern is that you can have 200 "big red" soldiers sharing the same "big red" graphical representation, 300 "small blue" soldiers sharing the same "small blue" graphical representation, etc. If you make the graphical representation static, all the soldiers will be identical.

Melodiemelodion answered 23/2, 2013 at 14:42 Comment(9)
in other words, a flyweight acts as a "prototype" referenced from many objects to save memoryAdagietto
What if you have a static collection of different graphical representations? This patterns seems to be very convoluted to me and it is more like an antipatternGuilder
Then every soldier will have a reference to one of the graphical representations of this static collection. Assuming the list is of size 5, and the number of soldiers is 1,000,000, you'll have 5 instances of graphical representation, instead of 1,000,000. That's the point of the pattern.Melodiemelodion
Static variables are shared between all class instances so you would still only have 5 instances of graphical representations and 1,000,000 references to them. The pattern wouldn't save any memory.Guilder
Of course it would save memory. Let's say a soldier is represented by an image of 10 * 100 pixels, 4 bytes per pixels. That makes 4,000 bytes per graphical representation. With 5 instances, you need 20,000 bytes (20 KB). With 1,000,000 graphical representations, you need 4,000,000,000 bytes (4 GB). What costs is not the reference to the graphical representation (which just needs a 4-byte pointer), but the graphical representation itself.Melodiemelodion
No, you have a static collection of graphicalRepresentation objects, which is shared. This collection is associated with the type SoilderClient. So you could just say: SolderClient.GraphicalRepresentationCollection["bigBlue"] and that would return one of the 5 objects without having ANY instances of type SoilderClient. The number of SoilderClient objects does not affect the number of graphicalRepresentations. You would only ever have 5 of them. Those 5 objects are constructed when the type SoldierClient is loaded and they exist until the execution of your program finishes. Right?Guilder
How would a soldier know that it must use SolderClient.GraphicalRepresentationCollection["bigBlue"] and not SolderClient.GraphicalRepresentationCollection["smallRed"] or SolderClient.GraphicalRepresentationCollection["mediumGreen"]? Answer: by storing a reference to one of the static graphical representations (passed at creation time). So that's the flyweight pattern: a single heavyweight object is shared between dozens of objects sharing common state.Melodiemelodion
How about SoilderClient mySoldier = new SoilderClient(SolderClient.GraphicalRepresentationCollection["smallRed"])? at construction time or mySolder.SetGraphicalRepresentation(SolderClient.GraphicalRepresentationCollection["smallRed"]) at any later stage?Guilder
Yes, that's it. You just used the flyweight pattern. Not using it would be SoldierClient mySoldier = new SoldierClient(new SmallRedGraphicalRepresentation());Melodiemelodion
B
3

Static fields work, no matter how many red/green/blue graphical representations you may have. The only problem with static fields is that they break Single Responsibility Principle. As you see, your SoldierClient class has two jobs:

  1. managing a pool of graphical representations
  2. the job of a typical SoldierClient

With this design, it's very difficult to reuse one of these two jobs in another context. For example, the pool cannot be reuse for Monster objects which also need to share graphical representations; the typical SoldierClient cannot be used in another context which has nothing to do with a pool.

Baillie answered 12/10, 2016 at 10:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.