8
Structural Pattern: Flyweight To maximize flexibility, it is often advantageous to model objects down to very fine levels of granularity. Chapter 4 – Page 1 However, when very large numbers of such objects are needed in an application, this level of granularity can be prohibitively expensive in terms of performance and memory usage. The Flyweight Pattern tackles this problem by splitting the objects into their extrinsic (i.e., state-dependent) and intrinsic (state- independent) components. The intrinsic parts are shared within the Flyweight object, while the extrinsic parts are controlled by the client and passed to the Flyweight as

Structural Pattern: Flyweight

  • Upload
    thimba

  • View
    23

  • Download
    0

Embed Size (px)

DESCRIPTION

Structural Pattern: Flyweight. Chapter 4 – Page 109. To maximize flexibility, it is often advantageous to model objects down to very fine levels of granularity. - PowerPoint PPT Presentation

Citation preview

Page 1: Structural Pattern: Flyweight

Structural Pattern: FlyweightTo maximize flexibility, it is often advantageous to model objects down to very fine levels of granularity.

Chapter 4 – Page 1

However, when very large numbers of such objects are needed in an application, this level of granularity can be prohibitively expensive in terms of performance and memory usage.The Flyweight Pattern tackles this problem by splitting the objects into their extrinsic (i.e., state-dependent) and intrinsic (state-independent) components. The intrinsic parts are

shared within the Flyweight object, while the extrinsic parts are controlled by the client and passed to the Flyweight as needed.

Page 2: Structural Pattern: Flyweight

The Flyweight PatternChapter 4 – Page 2

The Client maintains a reference to the Flyweight objects and computes or stores their extrinsic state.The FlyweightFactory creates and manages the Flyweight objects, ensuring proper sharing (i.e., if a client needs a Flyweight, the FlyweightFactory supplies an existing one or, if none exists, creates a new one).

UnsharedConcreteFlyweightintrinsicState

operation(in extrinsicState) : void

Client

ConcreteFlyweightallState

operation(in extrinsicState) : void

FlyweightFactory

getFlyweight(in flyweightKey) : Flyweight

Flyweight

operation(in extrinsicState) : void

+flyweights

The Flyweight declares an interface through which the concrete Flyweight objects can deal with their extrinsic state.The ConcreteFlyweight implements the Flyweight interface and adds storage for its intrinsic state; although the Flyweight interface enables sharing, UnsharedConcreteFlyweight objects may exist.

Page 3: Structural Pattern: Flyweight

Non-Software Flyweight ExampleThe public switched telephone

network is an example of a Flyweight.

Chapter 4 – Page 3

There are several resources (ConcreteFlyweights) such as dial tone generators, ringing generators, and digit receivers that must be shared between all subscribers.

A subscriber (the Client) is unaware of how many resources are in the pool when he or she lifts the handset to make a call.

All that matters to subscribers is that a dial tone is provided, digits are received, and the call is completed.

Page 4: Structural Pattern: Flyweight

C++ Flyweight Pattern ExampleChapter 4 – Page 4/* Network links are the Flyweight objects here, with the technology type being used (e.g., *//* MPLS, BGP) as their intrinsic features and their adjacent nodes (types include core routers, *//* provider-edge routers, and subscriber-edge routers), adjacent interfaces (types include IP, *//* ATM, etc.), and IP address ranges as their extrinsic features. *//* *//* When each link in the network is capable of supporting several IP addresss, specific IP *//* addresses must be assigned to the interfaces supported by the links between adjacent nodes, *//* which, for elaborate networks, can become a prohibitive task. */

#include <iostream>#include <string>#include "RealLink.h"using namespace std;

void main(){ GenericLinkContext* aLinkContext = new GenericLinkContext();

RealLink* aLink = new RealLink("MPLS", "Core Router A", "Core Router B", "Interface IP", "Interface ATM", aLinkContext);

RealLink* anotherLink = new RealLink("BGP", "Core Router X", "Edge Router Y", "Interface ATM", "Interface IP", aLinkContext);

aLinkContext->SetAddressRange(anotherLink->mySlotNumber, "11.61.1.x", 6, 9); aLinkContext->SetAddressRange(aLink->mySlotNumber, "10.81.1.x", 0, 7);

cout << "For the " << aLink->GetTechnologyType() << " link, the IP Address range is " << aLink->GetAllIPAddresses() << endl << endl;

cout << "For the " << anotherLink->GetTechnologyType() << " link, the IP Address range is " << anotherLink->GetAllIPAddresses() << endl << endl;}

Page 5: Structural Pattern: Flyweight

Chapter 4 – Page 5#include <string>using namespace std;

class GenericLinkContext{ public: explicit GenericLinkContext() { SetNextFreeSlot(-1); } virtual ~GenericLinkContext() {} virtual int GetNextFreeSlot() { if (nextFreeSlot < MAX_ARRAY_LENGTH) return ++nextFreeSlot; else return nextFreeSlot; } virtual void SetNextFreeSlot(int theNextFreeSlot) { nextFreeSlot = theNextFreeSlot; } virtual void SetAddressRange(int slot, string baseAddress, int offset, int range) { AddressRangeArray[slot].baseRangeAddress = baseAddress; AddressRangeArray[slot].addressOffset = offset; AddressRangeArray[slot].addressRange = range; } virtual string GetBaseAddress(int slot) { return AddressRangeArray[slot].baseRangeAddress; } virtual int GetAddressOffset(int slot) { return AddressRangeArray[slot].addressOffset; } virtual int GetAddressRange(int slot) { return AddressRangeArray[slot].addressRange; } private: int nextFreeSlot; static const int MAX_ARRAY_LENGTH = 10;

/* Each entry in the array AddressRangeArray stores the IP address range details */ /* for a given link. Each link has an associated slot in this array. So when a new */ /* link must be created with a specific IP address range, the nextFreeSlot value */ /* is retrieved by invoking GetNextFreeSlot(). If the value is less than the */ /* maximum (10), a new address range array slot will be allocated. Once this new */ /* slot is obtained, the IP address range can be supplied via SetAddressRange(). */ struct AddressRanges { string baseRangeAddress; int addressOffset; int addressRange; } AddressRangeArray[MAX_ARRAY_LENGTH];};

Page 6: Structural Pattern: Flyweight

Chapter 4 – Page 6

#include "GenericLinkContext.h"#include <string>using namespace std;

class GenericLink{public: explicit GenericLink(GenericLinkContext* aLinkContext, string nodeA, string nodeB, string ifA, string ifB) { linkContext = aLinkContext; mySlotNumber = linkContext->GetNextFreeSlot();

NodeA = nodeA; NodeB = nodeB; InterfaceA = ifA; InterfaceB = ifB; } virtual ~GenericLink() {}

protected: GenericLinkContext* linkContext;

public: int mySlotNumber;

private: string NodeA; string NodeB; string InterfaceA; // Each interface can support many IP addresses string InterfaceB; // Each interface can support many IP addresses};

Page 7: Structural Pattern: Flyweight

Chapter 4 – Page 7#include "GenericLink.h"

#include <string>using namespace std;

class RealLink : public GenericLink{ public: explicit RealLink(string aTechnologyType, string nodeA, string nodeB, string ifA, string ifB, GenericLinkContext* aLinkContext): GenericLink(aLinkContext, nodeA, nodeB, ifA, ifB) { technologyType = aTechnologyType; } virtual ~RealLink() {} string GetAllIPAddresses() { string ipAddressRange = "";

int addressOffset = linkContext->GetAddressOffset(mySlotNumber); int addressRange = linkContext->GetAddressRange(mySlotNumber); ipAddressRange = ipAddressRange + linkContext->GetBaseAddress(mySlotNumber) + " - " + linkContext->GetBaseAddress(mySlotNumber); int index = 0; while (ipAddressRange[index] != 'x') index++; ipAddressRange[index] = addressOffset + '0'; while (ipAddressRange[index] != 'x') index++; ipAddressRange[index] = addressRange + '0'; return ipAddressRange; }

string GetTechnologyType() { return technologyType; }

private: string technologyType;};

Page 8: Structural Pattern: Flyweight

Flyweight Pattern AdvantagesChapter 4 – Page 8

• There are cases in programming where it seems that a very large number of small class instances is needed to represent data.

• Essentially, the variables that differ can be moved outside of the class instance and passed in as part of a method call.

• If the instances are fundamentally the same except for a few parameters, the number of instantiations can be greatly reduced by means of the Flyweight Pattern.

• While the Flyweight Pattern is not commonly used in application software, it does provide a useful technique for managing resources at the system level.