By: B. Woolf
Published in: PLoPD1
Pages: 467- 498
Category: Smalltalk ValueModel Idioms
Summary: ValueModel is a framework in VisualWorks Smalltalk. This collection describes ValueModels and how to use them.
ValueModel is a framework in VisualWorks Smalltalk. Describes ValueModels and how to use them.
To allow one object to retrieve and change a collaborator object in a uniform way, use a ValueModel to store the value. ValueModel is an abstract class, so you'll actually use an instance of one of its concrete subclasses.
To allow two objects to share a common value so that both can access and change it, and when one object changes it, the other is notified automatically, place the common value in a shared ValueModel. The sharing objects can register their interest, and the ValueModel will notify them when the value changes.
To allow an object using the value in a ValueModel to be notified when the value changes, to register your interest, send the ValueModel "aValueModel onChangeSend: aSelector to: aDependent", in which aSelector is the name of the method to run when the value changes, and aDependent is the object that contains the method (usually "yourself").
If the update performed when a change occurs is so simple that a separate "<something>Changed" method seems unnecessary, eliminate this step and use a ValueModel instead. This will connect the parent and dependent models using two ValueModels.
When should you use "value" and "value:"? Implement separate messages for accessing an object's aspects or values and the ValueModels that contain those aspects.
How can multiple objects that need to share the same value be assured of sharing a single ValueModel? When an instance variable holds a ValueModel, create a get method for it but not a set method, and initialize it in the initialize method. This will ensure that it will only be set once and never reset.
When an object gets a value from a ValueModel, how does it know the type of object it will receive? When defining a variable's type as ValueModel, also specify the type of the ValueModel's value.
To wrap ValueModel behavior around objects in instance variables, use a ValueHolder. It will wrap the object and give it ValueModel behavior. Store the ValueHolder in the instance variable.
How can ValueModel behavior be wrapped around a retrieval of an aspect of another model? Use an AspectAdaptor. Unlike a ValueHolder, the object itself won't be wrapped with ValueModel behavior. Retrieving and storing the object as an aspect of its container model will be wrapped as a ValueModel.
When a view has a number of values, how can the user be allowed to change all of them without changing them in the ApplicationModel and then accept or cancel all the changes at once? Use a BufferedValueHolder as a layer of separation between the model and the ValueModel for a field. A regular ValueModel will immediately store a new value in the model, but the ValueModel stored inside a Buffered ValueHolder will suspend the new value until you tell it to commit to the model.
To convert a real-world quantity to a percentage so that when the quantity changes, the percentage is automatically recalculated, use a RangeAdaptor, a ValueModel that converts a number in a specified range into a percentage.
To wrap ValueModel behavior around an element in a collection, use an IndexedAdaptor to give a collection element the aspect value.
To wrap ValueModel behavior around an instance variable without changing the kind of object an instance variable holds, use SlotAdaptor to give an object's instance variable the aspect value. The SlotAdaptor will also allow the element to be shared by multiple dependents.
To wrap ValueModel behavior around an arbitrary portion of an object, use a PluggableAdaptor to hold an arbitrary portion of an object when no other kind of ValueModel will work.
When two objects want to share a value but each wants a different type, how can the value appear as the appropriate type for each? Use a TypeConverter to convert the type of object.
You're using the ValueModel framework. What object should keep track of how much a point's position on a grid has changed? Use a ScrollValueHolder to hold the scroll position of a point. Set the grid to be the minimum size of each step the point must take when it moves.
To set up a list so it can say which item is being used, use a SelectionInList to track a list and its current selection. When you register your interest in one of its aspects, it will notify you of changes.