Design patterns in C# – part 5 (Flyweight pattern)

Role

The Flyweight pattern promotes an efficient way to share common information present in small objects that occur in a system in large numbers. It thus helps reduce storage requirements when many values are duplicated.

Design

Flyweight Pattern Image

Implementation

  • Client -> TestFlyweightPattern (using Editor class)
  • FlyweightFactory -> EditorSignFactory
  • IFlyweight -> IEditorSign
  • Flyweight -> EditorSign
namespace FlyweightPattern
{
    public interface IEditorSign
    {
        void Insert(int row, int column, Editor editor);
    }
}
namespace FlyweightPattern
{
    public struct EditorSign : IEditorSign
    {
        public static readonly IEditorSign EmptySign = new EditorSign(null);
        private readonly char? _sign;

        internal EditorSign(char? c)
        {
            this._sign = c;
        }

        #region IEditorSign Members

        public void Insert(int row, int column, Editor editor)
        {
            if (this._sign != null)
            {
                editor.Insert((char) this._sign, row, column);
            }
        }

        #endregion
    }
}
using System.Collections.Generic;

namespace FlyweightPattern
{
    public class EditorSignFactory
    {
        private static readonly Dictionary Signs = new Dictionary();

        public EditorSignFactory()
        {
            for (int i = 32; i < 127; i++)
            {
                Signs.Add((char) i, new EditorSign((char) i));
            }
        }

        public IEditorSign this[char key]
        {
            get { return Signs.ContainsKey(key) ? Signs[key] : EditorSign.EmptySign; }
        }
    }
}

using System;
using System.Text;

namespace FlyweightPattern
{
public class Editor
{
private readonly char[][] _editorWindow;

public Editor(int rows, int columns)
{
this._editorWindow = new char[rows][];
this.InitializeEditorWindow(rows, columns);
}

private void InitializeEditorWindow(int rows, int columns)
{
for (int i = 0; i < rows; i++)
{
this._editorWindow[i] = new char[columns];

this.FillRowOnStart(i, columns);
}
}

private void FillRowOnStart(int i, int columns)
{
for (int j = 0; j < columns; j++)
{
this._editorWindow[i][j] = '#';
}
}

public void Insert(char sign, int row, int column)
{
if (row < this._editorWindow.Length && column < this._editorWindow[0].Length)
{
this._editorWindow[row][column] = sign;
}
}

public void Display()
{
StringBuilder line;
int rowLength = this._editorWindow.Length;

for (int i = 0; i < rowLength; i++)
{
int columnLength = this._editorWindow[0].Length;
line = new StringBuilder(columnLength);

for (int j = 0; j < columnLength; j++)
{
line.Append(this._editorWindow[i][j]);
}

Console.WriteLine(line);
}
}

public void DisplaySplit()
{
Console.WriteLine("\n—————————–\n");
}
}
}

namespace FlyweightPattern
{
public class TestFlyweightPattern
{
public static void Main()
{
var myEditor = new Editor(10, 14);
myEditor.Display();
myEditor.DisplaySplit();
var signFactory = new EditorSignFactory();

IEditorSign signA = signFactory['A'];

IEditorSign signI = signFactory['I'];
IEditorSign signt = signFactory['t'];
IEditorSign signs = signFactory['s'];
IEditorSign signw = signFactory['w'];
IEditorSign signo = signFactory['o'];
IEditorSign signr = signFactory['r'];
IEditorSign signk = signFactory['k'];
IEditorSign signi = signFactory['i'];
IEditorSign signn = signFactory['n'];
IEditorSign signg = signFactory['g'];

IEditorSign signSpace = signFactory[' '];
IEditorSign signInterjection = signFactory['!'];

IEditorSign signW = signFactory['W'];

for (int i = 0; i < 10; i++)
{
signA.Insert(0, i, myEditor);
}

signI.Insert(2, 0, myEditor);
signt.Insert(2, 1, myEditor);
signs.Insert(2, 2, myEditor);

signSpace.Insert(2, 3, myEditor);

signw.Insert(2, 4, myEditor);
signo.Insert(2, 5, myEditor);
signr.Insert(2, 6, myEditor);
signk.Insert(2, 7, myEditor);
signi.Insert(2, 8, myEditor);
signn.Insert(2, 9, myEditor);
signg.Insert(2, 10, myEditor);

signSpace.Insert(2, 11, myEditor);

signInterjection.Insert(2, 12, myEditor);
signInterjection.Insert(2, 13, myEditor);

signW.Insert(4, 1, myEditor);
signo.Insert(4, 2, myEditor);
signw.Insert(4, 3, myEditor);

myEditor.Display();
}
}
}

OUTPUT:

##############
##############
##############
##############
##############
##############
##############
##############
##############
##############

—————————–

AAAAAAAAAA####
##############
Its working !!
##############
#Wow##########
##############
##############
##############
##############
##############

Use when

There are:

  • Many objects to deal with in memory
  • Different kinds of state, which can be handled differently to achieve space savings
  • Groups of objects that share state
  • Ways of computing some of the state at runtime

You want to:

  • Implement a system despite severe memory constraints

Bibliography

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s