package container;
/** An attribute of a Decorable object, such as a graph vertex. The
* attribute serves as a key with which some value may be associated.
* For example, the COLOR attribute of a position may have value "red"
* or "black", or may not exist at all.
*
* The textbook discusses the decorator pattern in section 12.3.1.
* But it does not have an Attribute class. It allows COLOR to be any
* object that you care to use as a name for looking up the color
* (e.g., position.get(COLOR)). In fact, to create a new attribute,
* the book just makes a new object with "new Object()".
*
* But it is better to make COLOR refer to an object of a special
* class Attribute. So you create it with new Attribute("color").
*
* Here's why it's better for COLOR to be an instance of Attribute,
* rather than of Object:
*
*
* - It makes the code clearer if every kind of object
* has a type that indicates how that object can be used.
*
*
- That also makes the code safer, because the compiler will check
* that you are not mixing up attributes with other kinds of objects.
* For example, if you call Decorable.put() as put("red",COLOR)
* instead of put(COLOR,"red"), then the compiler will complain
* that "red" is not an Attribute, rather than assuming it is some
* kind of new attribute object, and blithely storing COLOR as its value.
*
*
- The methods of Decorable have very general names: get, put,
* remove. We might want a class that implements Decorable to also
* implement another interface with methods of those names. This is
* possible thanks to method overloading, as long as the two methods
* with the same name work on different kinds of objects. So it is
* good to "narrowly tailor" the interface so that the methods only
* work on attributes.
*
*
- Finally, once we have an Attribute class, we can make special
* methods for Attributes, in particular a toString() method that
* allows folks to print an attribute's name in order to see what
* their code is doing.
*
*
* Note: Each Attribute instance represents a different kind of
* attribute. So there will typically be only a few instances of this
* class: e.g., COLOR, VISTED, DISTANCE, etc. (But even though there
* is only one COLOR attribute, many different graph vertices could
* have values for that attribute.)
*/
public class Attribute {
/** A name supplied by the user for printing this attribute.
* There may be multiple attribute objects with the same name,
* but they are considered to be different objects.
*/
private String name;
/** Constructor. Creates a new attribute. Each DecorablePosition
* can then optionally store a value for this attribute.
*
* @param name a meaningful name used only for printing the attribute.
*/
public Attribute(String name) {
this.name = name;
}
/** A printable representation of this attribute, such as
* "[attribute @12345 - color]" for a color attribute.
*
* The @12345 part is computed from the attribute's hash code, just
* as in the default Object.toString() method. It is included to
* distinguish multiple distinct attributes that might
* coincidentally happen to have the same user-supplied name.
*
* (Example: If two different classes both happen to call new
* Attribute("color"), then they will get distinct attributes, which
* is a Good Thing. Those attributes will print out as, for
* example, [attribute @12345 - color] and [attribute @12388 - color].)
*/
public String toString() {
return "[attribute @"+Integer.toHexString(hashCode())+" - "+name+"]";
}
}