6

I recently learned about Flyweight Pattern from this link.

It is written there:

It’s very important that the flyweight objects are immutable: any operation on the state must be performed by the factory.

I did not understand this well. Any opinion will be appreciated.

13

Flyweight objects must be immutable because our factory can only guarantee that it has remembered the correct object if it can also guarantee that the object it originally created has not been modified.

Flyweight objects provide a memory-efficient way to share common state between objects. This common state is called "intrinsic." Intrinsic state must be kept immutable, because if you change it, you change it for every object sharing the intrinsic state.

The immutable nature of the intrinsic state also allows the flyweight to be thread-safe.

There are several descriptions of Flyweight on the Internet, but most of them are not very good. The best one I've found so far is here: https://refactoring.guru/design-patterns/flyweight

  • So not the "Flyweight objects must be immutable", as your initial statement imposes, but the part of them which represents the intrinsic state, right? – Doc Brown Nov 7 '18 at 12:29
  • @DocBrown: That is my understanding, yes. The part that is "flyweight" is essentially the intrinsic part. – Robert Harvey Nov 7 '18 at 16:03
  • I always thought the "intrinsic part" is the heavyweight part, whilst the flyweight part is exactly the small part which can be mutated. – Doc Brown Nov 7 '18 at 17:42
  • @DocBrown: The intrinsic state is heavyweight, but it is shared among many object instances, which is what saves so much memory and gives the flyweight pattern its name. – Robert Harvey Nov 7 '18 at 17:51
  • Yes, but when the flyweight part can be mutable, then this invalidates your very first statement in this (otherwise excellent) answer. And this distinction is probably exactly where the question comes from. – Doc Brown Nov 7 '18 at 20:17
3

While the fly-weight pattern defines itself as having immutable 'fly-weight' objects, it will still achieve its goal of reducing RAM usage if you don't make them immutable.

The issue with making the objects mutable is that say for example your 'Tree' object has several properties, some are stored on a fly-weight object and some belong to the instance.

public class Tree
{
    public int x { get; set;}
    public int y { get; set;}
    private static flyTree; //shared across many trees
    public int Colour 
    {
        get { return flyTree.Colour;}
        set { flyTree.Colour = value;}
    }
}

When you change, for example, the x and y coordinates they will change for that instance of Tree only. But when you change colour it will change for all Trees.

As a user of the Tree object you wont have an easy way to tell which properties belong to the tree and which belong to the underlying fly-weight object.

Making the fly-weight shared part of the Tree immutable prevents a developer accidentally changing a property on all Trees when they mean to change it only for one Tree.

1

The others already mentioned that the pattern typically does have to be immutable since otherwise the pattern breaks down, but they're wrong in that it's absolutely has to be immutable. Copy-on-write is essentially how you'd make something that uses the fly-weight pattern and is mutable. That's how memory is shared, for example. The flyweight object can be used until any form of modification takes place, at which time a copy must be made.

That can be a bit tricky or error prone, however. The flyweight must be aware of all the ways that the underlying objects can be mutated and there must be hooks into all of them. It only really makes sense if things are frequently not mutated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.