chapter 13 flyweight

114
Chapter 13 Flyweight Summary prepared by Kirk Scott 1

Upload: liko

Post on 23-Feb-2016

46 views

Category:

Documents


0 download

DESCRIPTION

Chapter 13 Flyweight. Summary prepared by Kirk Scott. Design Patterns in Java Chapter 13 Flyweight. Summary prepared by Kirk Scott. That animal is known as a couscous A trip to Wikipedia will allow you to determine whether it is related to the food named couscous…. Introduction. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Chapter 13 Flyweight

1

Chapter 13Flyweight

Summary prepared by Kirk Scott

Page 2: Chapter 13 Flyweight

2

Design Patterns in JavaChapter 13Flyweight

Summary prepared by Kirk Scott

Page 3: Chapter 13 Flyweight

3

Page 4: Chapter 13 Flyweight

4

• That animal is known as a couscous• A trip to Wikipedia will allow you to determine

whether it is related to the food named couscous…

Page 5: Chapter 13 Flyweight

5

Introduction

• Under the principle that responsibility is localized, when programming, typically just one object will hold a single reference to another object

• This is related to the idea of cloning• Shallow copies with shared references are not

good• In general, any two objects, not necessarily clones

of each other, with references to the same object may be problematic

Page 6: Chapter 13 Flyweight

6

• Ideally, just one object holds a reference to another

• Any change to the held object will be a result of a call made in the holding object

• If this is the case, the holding object knows what’s been done

• If no other object holds a reference, no other object needs to be aware of a change

Page 7: Chapter 13 Flyweight

7

• On the other hand, some objects may be referred to by many other objects

• Alternatively, a single object may be referred to many times by one other object

• Put another way, one or more clients may want to share access to the same object

Page 8: Chapter 13 Flyweight

8

• Many clients/references are potentially capable of making changes to the shared object

• Therefore, many clients/references may have to be informed of a change

• The flyweight design pattern is intended to effectively manage this shared responsibility for shared objects/references

Page 9: Chapter 13 Flyweight

9

Initial Scenario

• The authors offer this scenario for sharing• Suppose that in a text management system there

is a single object for each printable character• Then a book may contain thousands of references

to individual instances of the character class• Also, there may be many books overall, each

containing multiple references to instances of the character class

Page 10: Chapter 13 Flyweight

10

• In this scenario it is the individual character objects that will be implemented using the flyweight design pattern

• What characteristics the flyweights have and how to manage them are at the heart of the pattern

Page 11: Chapter 13 Flyweight

11

Book Definition of Pattern

• Book definition:• The intent of the Flyweight pattern is to use

sharing to support large numbers of fine-grained objects efficiently.

• Comment mode on:• Not just large numbers of objects, but

potentially large numbers of references to those objects

Page 12: Chapter 13 Flyweight

12

Immutability

• Part of the introductory discussion mentioned the idea that if a shared object is changed, then potentially all clients should be notified

• They may or may not be notified• The real point is that a single action by one

client on an object can potentially affect many other clients with shared references to that object

Page 13: Chapter 13 Flyweight

13

• This kind of dependence among the clients can be an undesirable kind of coupling or dependence

• Also, if you want to notify other clients of changes, trying to do that may be onerous

• (Although using observability comes to mind as a possible solution)

Page 14: Chapter 13 Flyweight

14

• In general, the problem can be solved by simply making the flyweights immutable

• This means that their implementation contains no method that allows them to be changed by a client

Page 15: Chapter 13 Flyweight

15

• References to immutable objects may be dropped

• New instances with new values may be created

• But an existing object cannot be changed• You are familiar with immutability through the

Java String class

Page 16: Chapter 13 Flyweight

16

• At first glance, this may seem like one of those solutions where in order to save the villages it was necessary to destroy the villages

• In other words, you eliminate update problems by preventing updating

• But what if updating is important?

Page 17: Chapter 13 Flyweight

17

• Although immutability is key to the implementation of flyweights, it’s not their only aspect

• The full application of the pattern will include “identifying the immutable part” of something and implementing that part as an immutable flyweight

• There will still be room for other characteristics in the design

Page 18: Chapter 13 Flyweight

18

String Immutability, Good or Bad?

• Challenge 13.1• “Provide a justification of why the creators of

Java made String objects immutable, or argue that this was an unwise restriction.”

Page 19: Chapter 13 Flyweight

19

Good

• “An argument for the immutability of strings:”• This is a paraphrase of the book’s answer:• Strings are frequently shared• In other words, the system is supplying a class

with this flyweight-like characteristic• Therefore, to solve the difficulties of shared

references, it was a good thing to make them into flyweights by making them immutable

Page 20: Chapter 13 Flyweight

20

• Comment mode on:• The immutability of strings comes up in CSCE

202 when discussing encapsulation and cloning

• The book also touches on this, but not very clearly

• The general rule, as presented in CSCE 202, is repeated very briefly here

Page 21: Chapter 13 Flyweight

21

• When you have objects with instance variables that are references to objects, how should you write the get methods for them?

• You should probably return a clone• It violates encapsulation to return a reference• However, this problem is solved if the reference

returned is to an immutable object• So the immutability of Strings allows get methods to

return references to them without violating encapsulation

Page 22: Chapter 13 Flyweight

22

Bad

• “An argument against the immutability of strings:”

• This is a paraphrase of the book’s answer:• By definition, making strings immutable makes

it impossible to change them• This is an artificial limitation on strings that

doesn’t apply to most other objects

Page 23: Chapter 13 Flyweight

23

• This means Java is less flexible and contains special cases that you have to learn

• The authors observe that no language can completely protect the programmer from programming difficulties or making mistakes

• If that’s the purpose of immutability, it’s a fool’s errand

Page 24: Chapter 13 Flyweight

24

• The Call of the Wild, Chapter 5 (near the end):• “Thornton went on whittling. It was idle, he

knew, to get between a fool and his folly; while two or three fools more or less would not alter the scheme of things.”

• The Java API developers struck a balance• By making strings immutable, they supported

simple get methods without the concern of cloning

Page 25: Chapter 13 Flyweight

25

Extracting the Immutable Part of a Flyweight

• With multiple references, it can be useful for a shared object to be immutable

• Forget the argument about whether it was desirable for strings to be immutable

• For the purposes of this design pattern, it is the case that the flyweight class should be immutable

• The design pattern requires it and there is no choice

Page 26: Chapter 13 Flyweight

26

• This section starts with a design with lots of shared references to objects which are not flyweights

• The problem is that these objects are not immutable

• You want to refactor to a design that uses flyweights

Page 27: Chapter 13 Flyweight

27

• The primary goal of refactoring is to extract the immutable part of the class that the shared references are instances of

• This immutable part will become a new flyweight class

• Other parts of the original class will have to be handled in a different way

• These changes in the shared references will also require changes in the application that shares them

Page 28: Chapter 13 Flyweight

28

Example

• The book bases its example on chemicals• In a fireworks factory, the ingredients are

chemical in nature• In the non-flyweight design, the ingredients

are referred to as substances• The following UML diagram shows the

substance class

Page 29: Chapter 13 Flyweight

29

Page 30: Chapter 13 Flyweight

30

• The Substance class has instance variables for name, symbol, atomicWeight, and grams

• A digression on terminology:• The instance variables symbol and

atomicWeight suggest that we’re talking about chemical elements

• An element has a symbol and an atomic weight

Page 31: Chapter 13 Flyweight

31

• For what it’s worth, the following information is given by Wikipedia:

• The IUPAC definition[1] of atomic weight is:• An atomic weight (relative atomic mass) of an

element from a specified source is the ratio of the average mass per atom of the element to 1/12 of the mass of an atom of 12C.

Page 32: Chapter 13 Flyweight

32

• It becomes apparent that the authors want to refer to chemical compounds as well as elements

• When they refer to a symbol, they don’t just mean a single symbol for an element

• They also mean the chemical formula for a compound

• Technically, they might also have referred to molecular weight, which is the equivalent for compounds of atomic weight for elements

Page 33: Chapter 13 Flyweight

33

Distinguishing Mutable from Immutable Attributes

• The name, symbol, and atomicWeight instance variables of the Substance class identify and give characteristics of chemical elements and compounds

• They tell “what it is”• For any given instance of the Substance class,

these attributes would not change• Depending on how the code is structured, they

could become attributes of immutable objects

Page 34: Chapter 13 Flyweight

34

• The instance variable gram is different• Grams are a measurement of mass (what we

poor benighted users of the English system think of as weight)

• It tells “how much there is” • For any given instance of the Substance class, the

value of this attribute could vary• Depending on how the code is structured, this

could become an attribute of mutable objects

Page 35: Chapter 13 Flyweight

35

• In short, the Substance class tells both what something is and how much of it there is

• Such a class invites decomposition into two parts, and logically speaking, this is evident for two reasons:

• 1. If you have two kinds of information, that alone may suggest that two classes are desirable

Page 36: Chapter 13 Flyweight

36

• 2. The second reason implies the flyweight/immutability argument:

• The Substance class is not a singleton• You can have multiple instances of it• If you do, repeating the “what it is”

information is redundant• The difference between the instances of the

class would only be in the “how much”

Page 37: Chapter 13 Flyweight

37

Additional Information in the UML Diagram

• The UML diagram only showed get methods, but in general, the Substance class would also have set methods

• This is why it is mutable• For what it’s worth, it also has a computed

getMoles() method that returns the number of moles (6.02 x 1023 molecules, Avogadro’s number of molecules) in a given mass of an element or compound

Page 38: Chapter 13 Flyweight

38

Instances of the Mixture Class share References to Substance Objects

• In the fireworks scenario, there are mixtures of substances as well as substances.

• A mixture is a combination of chemicals which are not bound together in a single chemical compound.

• The next overhead shows how an instance of the Mixture class is based on having references to instances of the Substance class

Page 39: Chapter 13 Flyweight

39

Page 40: Chapter 13 Flyweight

40

• In the fireworks setting there could be many different mixtures that have to be modeled

• There would be many references to instances of the Substance class

• The number of grams could differ among different instances of the substance class

Page 41: Chapter 13 Flyweight

41

• The chemical compound attributes could be the same for multiple instances of the class

• Forget about the cosmic difficulties of mutability for a moment

• Notice that if there are lots of instance of Substance, there is a lot of redundancy

Page 42: Chapter 13 Flyweight

42

Refactoring the Design

• Challenge 13.2• “Complete the class diagram in Figure 13.3 to show

a refactored Substance2 class and a new, immutable Chemical class.”

• Comment mode on:• For a change I’m leaving this as a challenge• It is worth considering the two steps:• Divide the design into two classes• Figure out what goes into each

Page 43: Chapter 13 Flyweight

43

Page 44: Chapter 13 Flyweight

44

• Solution 13.2• “You can move the immutable aspects of

Substance—including its name, symbol, and atomic weight—into the Chemical class, as Figure B.17 shows.”

Page 45: Chapter 13 Flyweight

45

Page 46: Chapter 13 Flyweight

46

• Solution 13.2, continued• “The Substance2 class now maintains a reference

to a Chemical object.• As a result, the Substance2 class can still offer the

same accessors as the earlier Substance class.• Internally, these accessors rely on the Chemical

class, as the following Substance2 methods demonstrate.”

• [See the next overhead.]

Page 47: Chapter 13 Flyweight

47

• public double getAtomicWeight()• {• return chemical.getAtomicWeight();• }• public double getGrams()• {• return grams;• }• public double getMoles()• {• return grams / getAtomicWeight();• }

Page 48: Chapter 13 Flyweight

48

Flyweight and Object Adapter

• You might observe that we saw code very like this in the adapter pattern, for example

• Informally, what has been accomplished is this:

• Instances of Substance2 “wrap” references to Chemicals

Page 49: Chapter 13 Flyweight

49

• Substance2 provides an interface to the chemicals to the client

• The Substance2 interface is implemented by delegation, calling methods on the wrapped chemical object

Page 50: Chapter 13 Flyweight

50

Sharing Flyweights

• Extracting the immutable part of a class in order to create flyweights is one part of applying the Flyweight pattern

• Notice that there should only be one instance of the Chemical class for each kind of chemical

• Applying the pattern also includes creating a “flyweight factory”

• This will control the construction of instances

Page 51: Chapter 13 Flyweight

51

• For the example the book proposes a ChemicalFactory class

• It will contain a static method that will return a reference to a chemical given the chemical’s name

• Internally the factory class will store the different chemicals in a hash table

Page 52: Chapter 13 Flyweight

52

• You may recall that the book’s example of the mediator involved the use of a hash table

• It was used, among other things, to make sure there was only one reference to each tub

• It can also be use to make sure there is only one instance of each chemical

Page 53: Chapter 13 Flyweight

53

• The UML diagram on the next overhead illustrates the relationships between the ChemicalFactory class and the Chemical class

Page 54: Chapter 13 Flyweight

54

Page 55: Chapter 13 Flyweight

55

Implementing the ChemicalFactory Class

• The ChemicalFactory class will only contain static things

• In that respect it will be like the Math class, for example

• There is no need to construct an instance of the class, and it doesn’t have a constructor

Page 56: Chapter 13 Flyweight

56

• The ChemicalFactory class contains a static HashMap which holds instances of chemicals

• The empty HashMap is created using inline construction where it is declared in ChemicalFactory

Page 57: Chapter 13 Flyweight

57

• The book uses what it calls a static initializer for the HashMap

• This is a block of code that follows the inline construction of the HashMap and constructs instances of chemicals, putting them into the HashMap

• Because the initializer is declared static, it is run once, when the class is loaded.

Page 58: Chapter 13 Flyweight

58

• The overall purpose of the class is to make chemicals available.

• The class contains a static method to retrieve references to chemicals (from the hash table) and return them to callers

• It is called like any static method—like the methods of the Math class, for example

Page 59: Chapter 13 Flyweight

59

• Partial code for the ChemicalFactory class is shown on the following overheads

Page 60: Chapter 13 Flyweight

60

• import java.util.*;• public class ChemicalFactory• {• private static Map chemicals = new HashMap();• static • {• chemicals.put("carbon", new Chemical("Carbon", "C",

12));• chemicals.put("sulfur", new Chemical("Sulfur", "S",

32));• chemicals.put("saltpeter", new Chemical("Saltpeter",

"KN03", 101));• //...• }• public static Chemical getChemical(String name)• {• return (Chemical) chemicals.get(name.toLowerCase());• }• }

Page 61: Chapter 13 Flyweight

61

Static Classes and Singletons

• This is tangential to the flyweight pattern, but it further illuminates the singleton pattern:

• A singleton class, ChemicalFactorySingleton, would be an alternative to the ChemicalFactory class containing only static methods

Page 62: Chapter 13 Flyweight

62

• The static initialization code for the HashMap and its contents could be put into the constructor for the singleton

• Then in client code, instead of calling static methods, you would create the one instance of the singleton factory and call a non-static getChemical() method on that instance

Page 63: Chapter 13 Flyweight

63

Making Sure that Only One Instance of Each Chemical is Created

• Developers should not create their own instances of the chemical class

• They should only use the chemicals in the ChemicalFactory class, acquiring references by calling the getChemical() method

• Enforcing this discipline can be accomplished by controlling access to the Chemical class

Page 64: Chapter 13 Flyweight

64

• Challenge 13.3• “How can you use the accessibility of the

Chemical class to discourage other developers from instantiating Chemical objects?”

Page 65: Chapter 13 Flyweight

65

• Solution 13.3• “One way that won’t work is to make the Chemical

constructor private.• That would prevent the ChemicalFactory class

from instantiating the Chemical class”• Comment mode on:• This may be in the back of your mind based on

having seen the singleton pattern• However, this alone is not the solution

Page 66: Chapter 13 Flyweight

66

• “To help prevent developers from instantiating the Chemical class themselves, you could place Chemical and ChemicalFactory classes in the same package and give the Chemical class’s constructor default (“package”) access.”

• Comment mode on:• Relying on access modifiers alone is not a very

strong solution

Page 67: Chapter 13 Flyweight

67

• The book continues the discussion in the body of the text, following the challenge

• You could also prevent client code from creating instances of the Chemical class by making it an inner class of the ChemicalFactory class

• Keep in mind that the authors are not very good about using private access when it would be the best choice

• They use package or protected access when it’s convenient to them

Page 68: Chapter 13 Flyweight

68

• There is confusion in the book’s presentation at this point due to their lack of discipline

• The text explains things in terms of a private inner class with a public constructor.

• But when you see their code, you discover they’ve punted by writing an inner class with no access modifier and a constructor with no access modifier (package access for both)

Page 69: Chapter 13 Flyweight

69

• The discussion here will proceed under the assumption that the class is private but the constructor is public

• You have seen private inner classes before• Recall that that was done with the inner class

implementations of listeners in CSCE 202• If the nested class is private, then its public

constructor can only be called within the code of the containing class

Page 70: Chapter 13 Flyweight

70

References to Chemical Objects Are Still Accessible in Client Code

• Even though the Chemical class is private, instances of it can be accessed elsewhere

• Recall that you have to use a qualified name when using an inner class

Page 71: Chapter 13 Flyweight

71

• This line of code illustrates how the client would call the get method in the factory in order to acquire by name a reference to a desired chemical

• ChemicalFactory.Chemical c = ChemicalFactory.getChemical(“saltpeter”);

Page 72: Chapter 13 Flyweight

72

A More Elaborate Solution

• The book wants to develop its solution further• Two points have been made so far• 1. The flyweight should be immutable• 2. It shouldn’t be possible for the client to

construct instances of flyweights• In this new solution, an interface will be added

to the design to complete the protection of flyweights from the client

Page 73: Chapter 13 Flyweight

73

• Instead of a chemical class, the design will have an interface named Chemical

• The Chemical interface for this enhanced solution is shown on the next overhead

• It simply has in it the accessor methods associated with chemicals all along

Page 74: Chapter 13 Flyweight

74

• public interface Chemical• {• String getName();• String getSymbol();• double getAtomicWeight();• }

Page 75: Chapter 13 Flyweight

75

• Then the factory class will have an inner class named ChemicalImpl, short for ChemicalImplementation

• The inner class, ChemicalImpl, will implement the Chemical interface

• Instances of ChemicalImpl will be the actual chemical objects in the application

Page 76: Chapter 13 Flyweight

76

• It is a little premature, but in order to aid in explaining this, the complete UML diagram for the new design is given on the following overhead

• The same UML diagram will be repeated again after all of the different aspects have been discussed.

Page 77: Chapter 13 Flyweight

77

Page 78: Chapter 13 Flyweight

78

• Internal to the factory, instances of ChemicalImpl are created and stored in the hash table

• The hash table is typed to hold interface references, Chemical

• The getChemical() method of the factory is typed to return interface references, Chemical

• ChemicalImpl objects are returned, but they are returned under the interface type

Page 79: Chapter 13 Flyweight

79

• Client code is written to work with interface references of type Chemical

• Client code never works directly with an actual class reference to an instance of the ChemicalImpl inner class

Page 80: Chapter 13 Flyweight

80

• The previous solution protected the flyweight class, Chemical, by making it an inner class

• This was a complete solution as long as the flyweight inner class had no dangerous methods

• The theory was that if it was immutable, a reference could be returned

• However, there is a chance that there might be other methods that you wouldn’t want client programmers to use

Page 81: Chapter 13 Flyweight

81

• Using the interface, protection is ironclad• Regardless of what methods might have been

implemented in the inner class, the client code only has an interface reference to the chemical implementation object

• The client is only capable of calling methods defined in the interface, not methods defined only in the inner class

Page 82: Chapter 13 Flyweight

82

• As far as the client knows, it is simply dealing with chemicals

• It doesn’t have to know that chemicals are created as instances of a separate, inner class known as ChemicalImpl

• The client code can be blissfully unaware of the existence of the flyweight inner class and contain no references to it whatsoever

Page 83: Chapter 13 Flyweight

83

• This solution also has the following practical consequence on client code:

• The client never has to use a qualified name to refer to chemicals

• It refers to the chemicals by the interface name Chemical, not the inner class name

Page 84: Chapter 13 Flyweight

84

Code for the Latest Solution

• Challenge 13.4• Complete the following code for ChemicalFactory2.java• Comment mode on:• The given incomplete code is kind of long• Since I always just show the answer anyway, I’m

skipping the incomplete code and just going to the answer, which is on the following overheads

• This is the code where the authors have punted and used package access for the inner class and its constructor.

Page 85: Chapter 13 Flyweight

85

• import java.util.*;• public class ChemicalFactory2 • {• private static Map chemicals = new HashMap();

• class ChemicalImpl implements Chemical • {• private String name;• private String symbol;• private double atomicWeight;

• ChemicalImpl(String name, String symbol, double atomicWeight) • {• this.name = name;• this.symbol = symbol;• this.atomicWeight = atomicWeight;• }

Page 86: Chapter 13 Flyweight

86

• public String getName() • {• return name;• }

• public String getSymbol()• {• return symbol;• }

• public double getAtomicWeight() • {• return atomicWeight;• }

• public String toString() • {• return name + "(" + symbol + ")[" + atomicWeight +

"]";• }• }

Page 87: Chapter 13 Flyweight

87

• static • {• ChemicalFactory2 factory = new ChemicalFactory2();• chemicals.put("carbon", factory.new

ChemicalImpl("Carbon", "C", 12));• chemicals.put("sulfur", factory.new

ChemicalImpl("Sulfur", "S", 32));• chemicals.put("saltpeter", factory.new

ChemicalImpl("Saltpeter", "KN03", 101));• //...• }

• public static Chemical getChemical(String name) • {• return (Chemical) chemicals.get(name.toLowerCase());• }• }

Page 88: Chapter 13 Flyweight

88

UML for the Book’s Example

• A UML diagram that attempts to illustrate the complete book solution is given on the overhead following the next one

• In the diagram, only the ChemicalImpl class itself is literally the flyweight

• However, the use of a factory is an inherent part of the overall pattern

Page 89: Chapter 13 Flyweight

89

• The Client makes use of the ChemicalFactory class to obtain references to flyweights

• The flyweights are needed to represent the intrinsic characteristics of chemicals

• References to these chemicals occur in the references to instances of the Substance class, which the client manipulates

• The use of the interface Chemical makes for a better implementation

Page 90: Chapter 13 Flyweight

90

Page 91: Chapter 13 Flyweight

91

A Final Comment?

• It seems that a large part of what was accomplished might also have been accomplished by making the ChemicalImpl objects singletons

• Then references to the singletons could be acquired by calling a method that returns a reference (and potentially does lazy initialization) rather than calling a constructor

Page 92: Chapter 13 Flyweight

92

• However, the flyweight pattern, including immutability and the idea of a factory class possibly provide a more comprehensive solution

• We will see factory classes gain in two future patterns

Page 93: Chapter 13 Flyweight

93

Another Example

• Other units have had another example that was complete with a UML diagram and code

• The other example for this unit is merely an idea

• Think back to the other example for the mediator pattern

• It consisted of 3 cups containing 9 colored seeds

Page 94: Chapter 13 Flyweight

94

• Each seed could only be in one cup at a time• Now consider expanding the cups into visual

representations of sets in a Venn diagram• Each seed could be in (and appear in) more

than one (overlapping) cup at a time• This could be accomplished by cups’ sharing

references to seeds

Page 95: Chapter 13 Flyweight

95

• There is nothing difficult about this example• It wouldn’t be hard to make the seeds

immutable• Also, with so few seeds, a factory would hardly

seem to be necessary• However, with more cups and more seeds, the

flyweight design pattern might be useful

Page 96: Chapter 13 Flyweight

96

• This scenario can lead to an example that tests your understanding of the pattern

• A simple UML class diagram is shown on the following overhead.

• Based only on what is in the diagram and ignoring anything else that might not be shown either in that class or in the rest of an application that used it, is the class suitable for use as a flyweight?

Page 97: Chapter 13 Flyweight

97

+getSeedCount() : int+getContainingCup() : Cup

-seedCount : int-containingCup : Cup

Seed

Page 98: Chapter 13 Flyweight

98

• You could conceivably answer in two different ways:

• Yes, it's OK. • It's immutable. • The class only has get methods in it. • Not, it's not OK. • The getCup() method returns a reference, so it

violates encapsulation and isn't really immutable.

Page 99: Chapter 13 Flyweight

99

Comparing Flyweight with Other Patterns

• The singleton, object adapter, and mediator patterns have come up in the discussion of flyweight

• This is just a brief recap of some of the connections you might draw between the patterns

Page 100: Chapter 13 Flyweight

100

Flyweight and Singleton

• The flyweight class isn’t a singleton• There are multiple instances of a flyweight

class (character, chemical, seed, for example)• However, there can be no duplicate objects

that are instances of the flyweight class• No two instances of a flyweight should test

equal for contents

Page 101: Chapter 13 Flyweight

101

• A factory class is also needed for the pattern• The ChemicalFactory was given as a class

containing only static methods• What is accomplished with a class containing

static methods could be accomplished with a singleton class

• In essence, the factory is a kind of singleton, whether implemented that way or not

Page 102: Chapter 13 Flyweight

102

Flyweight and Object Adapter

• The observation here was that a client might have Substance objects which contained the mass of a quantity of a Chemical

• Obtaining the name of a substance’s Chemical relied on a wrapping a call to the get method on the contained flyweight reference to a Chemical

Page 103: Chapter 13 Flyweight

103

Flyweight and Mediator

• The flyweight factory is an important part of the application of the pattern as presented by the book

• The factory for flyweights has similarities with the mediator pattern

• The flyweight pattern depends on a factory class with a hash table containing a single column, the instances of flyweight

Page 104: Chapter 13 Flyweight

104

• The factory creates the flyweights, makes sure there are no duplicates, maintains a list of them, and makes them available for sharing

• The flyweights have to be immutable

Page 105: Chapter 13 Flyweight

105

Lasater’s UML

• It is worthwhile to compare with Lasater’s take on the design

• The diagrams aren’t exactly the same, but if you trace through them you see that they represent the same basic idea and similar structure using slightly different notation

Page 106: Chapter 13 Flyweight

106

• Lasater definitely shows a factory as part of the design• Lasater doesn’t include an interface or inner class as part

of the design• Instead, although not so labeled, the Flyweight class

appears to be abstract since it has concrete subclasses• The ConcreteFlyweight seems to correspond to a

substance• The UnsharedConcreteFlyweight seems to correspond to

a chemical

Page 107: Chapter 13 Flyweight

107

Page 108: Chapter 13 Flyweight

108

Summary

• The Flyweight pattern supports the sharing of one instance by many clients

• A flyweight class should be immutable• When refactoring a design to use the

flyweight pattern, part of the process is extracting the immutable part

Page 109: Chapter 13 Flyweight

109

• The instances of the flyweight should be created in a factory class

• The factory class should also manage making the flyweights available for sharing

• An inner class (possibly with an interface) gives the factory a suitable level of control over the creation of instances of the flyweight

• A static method can be used to return references to the (immutable) flyweight objects

Page 110: Chapter 13 Flyweight

110

• If the flyweight and the factory are correctly set up, you achieve these goals:

• Concretely, shared access is enabled• This shared access is safe and foolproof• Clients can’t create instances of their own

Page 111: Chapter 13 Flyweight

111

• In a broader sense, the refactoring accomplishes this:

• You avoid a proliferation of many instances of a class that has both mutable and immutable attributes

• This prevents redundancy

Page 112: Chapter 13 Flyweight

112

• More importantly, you avoid having shared references to classes with mutable attributes

• By not having shared references to mutable classes, you avoid the problem that many clients would be coupled

Page 113: Chapter 13 Flyweight

113

• A change to the shared object by one of the clients would affect all of them

• Without the flyweight solution you would be confronted with the problem of how to notify/update all of the clients

Page 114: Chapter 13 Flyweight

114

The End