DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Data
  4. A Story on the Flyweight Pattern

A Story on the Flyweight Pattern

Flyweight objects are a great way to manage memory by sharing common data among them. Here, we walk through the Flyweight Pattern to introduce a blog theme.

Shamik Mitra user avatar by
Shamik Mitra
·
Jun. 12, 17 · Tutorial
Like (14)
Save
Tweet
Share
14.63K Views

Join the DZone community and get the full member experience.

Join For Free

Image title

Jenny wants to introduce a theme in her blog, but she is facing a problem.

The Problem

Her blog is a combination of multiple widgets like a Header widget, a Footer widget, a Content widget, a Follower widget, etc.

And those widgets are populated by backend calls or web service calls to load widgets repetitively. That is a costly operation.

But Jenny wants to introduce her theme, which can reorder the widget position as well as the color of the widgets.

The question she asks is, every time a user changes the theme, should she reload the widget and populate the data?

That is very bad design, as it will load all those costly widgets again and again. That will slow down the response.

But the Theme Change operation is in the users' hands. Jenny can’t say, "Users, don't change the theme frequently!"

So What Does She Do Now?

Jenny goes to her OOP teacher for a solution. He tells her to reuse the widget, but she believes her widget is stateful, so she explains the problem she has having now.

Jenny: Sir, I can use a cache and match the widget against a key in the cache and reuse it, but say my default theme is Classic Blue, so every widget has a blue color. And say that in the Classic Blue theme, my Follower widget is on the left side of the screen. Now, if a user changes it to Slick Green, then every widget has to change their color to green. And say in the Slick Green theme that the Follower widget will be on the right side of the screen. Now, if I want to reuse my widget from the cache, it is blue and the Follower widget is on the left. How can I reuse them without populating a new widget?

Teacher: Very good, but think about the scenario here. Your widget populates data from the backend and loads once. But if you want to load it again just to assign a color and position, then you welcoming a potential danger to your blog. So, your new feature is not an addition, it is a technical debt. Then it is better not to have it.

Think in the OOP perspective. When you change the theme, what happens? It just reorders the widget position and changes the color. But the widget's content is the same. So, if the widget is loaded once and Jenny makes the widget capable of taking a color and position value from the outside, then can the widget be reused?

The answer is yes. Apart from color and position, the widget is state-independent in this context, as its content does not change.

One can easily pass any attribute from the outside and, based on the theme, your widget layout manager can decide the position and color of the widget.

The Flyweight Pattern can do that.

What Is the Flyweight Pattern?

According to Wikipedia:

"A flyweight is an object that minimizes memory usage 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."

So, according to the definition, widgets are Flyweight objects, and reloading them unnecessarily increases response time. So, instead, what if we share color and position data to all Flyweight objects/widgets? Then we can reuse them! The layout manager computes the value of color and position by using the theme, an external data structure.

So every Flyweight object has two kinds of data:

  1. Intrinsic data: state-independent data. Data that does not change with the context, like Jenny's widgets' content not changing with the theme.
  2. Extrinsic Data: context-dependent data that changes with the context, like our example widgets' color and position.

To make our Flyweight object reusable, we need to pass extrinsic data from outside to a Flyweight object.

Coding Time

IWidget.java:

/**
*
*/
package com.example.flyweight;

/**
* @author Shamik Mitra
*
*/
public interface IWidget {

    public void setWidgetName(String name);
    public String getWidgetName();
    public void setWidgetContent(String content);   
    public void display();
    public void applyTheme(String color,String postion,Layoutmanager manager);

}


Now we create a layout manager and use the Flyweight Pattern here:

/**
*
*/
package com.example.flyweight;

import java.util.HashMap;
import java.util.Map;

/**
* @author Shamik Mitra
*
*/
public class Layoutmanager {

    private static Layoutmanager mgr = new Layoutmanager();

    Map<String,IWidget> map = new HashMap<String,IWidget>();

    public static Layoutmanager get(){
        return mgr;
    }

    private Layoutmanager(){
        init();
    }


    public void addWidget(IWidget widget,String position){
        System.out.println("Adding Widget " + widget.getWidgetName()+  " in to position " + position);

    }

    private void init(){

        IWidget followerWidget = new IWidget(){

            private String name;
            private String content;
            private String color;
            private String position;

            @Override
            public void setWidgetName(String name) {
            this.name=name;
            }

            @Override
            public String getWidgetName() {
            return name;
            }

            @Override
            public void setWidgetContent(String content) {
            System.out.println("setting content first-time....loading from back end costly operation");
            this.content=content;

            }

            @Override
            public void display() {
                System.out.println(" Widget name : " + name);
                System.out.println(" Widget color : " + color);
                System.out.println(" Widget color : " + position);
                System.out.println(" Widget content : " + content);
            }

            @Override
            public void applyTheme(String color, String postion, Layoutmanager manager) {
                this.color=color;
                this.position=postion;
                manager.addWidget(this,postion);

            }

        };

        followerWidget.setWidgetName("Follower Widget");
        followerWidget.setWidgetContent("Showing blog Followers.");
        followerWidget.applyTheme("Blue", "LEFT", this);
        followerWidget.display();
        map.put(followerWidget.getWidgetName(), followerWidget);



    }


    public void changeTheme(){
        System.out.println("After Change Theme");
        for(String name : map.keySet()){
            if("Follower Widget".equalsIgnoreCase(name)){
                IWidget widget = map.get(name);
                widget.applyTheme("Green", "RIGHT", this);
                widget.display();
            }
        }
    }

    public static void main(String[] args) {
        Layoutmanager mgr = Layoutmanager.get();
        mgr.changeTheme();
    }



}


Explanation

In the Init() method, we've created the Follower widget for the first time and put it on a Map so later on, when the user does change the theme, the widget can be reused.

Then, apply the Classic Blue theme as the default theme.

When a user calls the ChangeTheme() method, the application calls every widget’s applyTheme() method and passes color and position data from the layout manager. That way, the widgets/Flyweights objects can change their color and set themselves in the correct position.

As mentioned, Color and Position are the extrinsic properties of the Flyweight objects.

Other widget properties are intrinsic in nature.

Further Improvements

Please note that this is a very basic example. To make it concrete, more improvements are needed, like:

  1. The theme has to be a context. The object implements an ITheme interface, which dictates what the color and other properties will be.
  2. The layout manager should be the implementation of the ILayoutManager interface, as there can be various layouts.
  3. The widget can be decorated via the Decorator Pattern.
  4. We can segregate the logic of widget creation and load it into the cache in a separate class called WidgetFlyWeightFactory.
Data (computing) Object (computer science)

Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Create and Edit Excel XLSX Documents in Java
  • Top Five Tools for AI-based Test Automation
  • Stream Processing vs. Batch Processing: What to Know
  • AWS Cloud Migration: Best Practices and Pitfalls to Avoid

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: