Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Applied Java™ Patterns - Stephen Stelting, Olav Maassen.pdf
Скачиваний:
198
Добавлен:
24.05.2014
Размер:
2.84 Mб
Скачать

JavaBeans

Packages

java.beans, java.beans.beancontext

Use: J2SE (since JDK1.1)

Overview

JavaBeans™ provides a standardized model for the Java programming language that enables classes to be developed as components. Components have a standard way of representing data and behavior, so they're more easily shared between developers. A component model such as JavaBeans potentially enables a developer to reuse another developer's code even if they work in different companies in different parts of the world. In the component model, technical roles are divided into component programmers, component assemblers, and application assemblers. The programmers are the only ones who actually have to code; the component and application assemblers use development tools that allowed them to visually manipulate and combine beans. This enables them to build new beans, or entire applications. JavaBeans can be visual, but they don't have to be.

That a component model is a good idea is demonstrated by the fact that components also underlie Java 2 Enterprise Edition, but the visual use of JavaBeans was only moderately successful.

However, that isn’t to say that JavaBeans are insignificant. When JavaBeans were conceived they required quite a change in Java. The old event model (hierarchical) had to be replaced with a more flexible event model so responsibilities could properly be distributed. The new event model became known as the delegation model. (See “ Event Handling ” on page 281.) This event model is core to the Java Beans architecture.

At the same time, emphasis was also placed on code conventions, because naming is an essential part of the introspection of JavaBeans. All of the AWT components became JavaBeans.

JavaBeans are generally supposed to support events, properties, introspection, customization, and persistence. The current event model allows decoupling event sources and event listeners. Every JavaBean can be a source of events and/or a listener to events. The JavaBean identifies itself as a listener by implementing the appropriate listener interfaces and methods defined in those interfaces. To identify itself as an event source, the bean has to

provide addXXXListener and removeXXX Listener methods.

For other tools and applications to find the properties of a JavaBean, the bean has to stick to specific method naming. If the bean has what we now know as getters and setters with a particular name, like String getName() and void setName(String n), then other applications can safely assume the bean has a property called name of a type String, even though the internal representation may be different. This property can then be used in property sheets of a visual editor or in other applications. JSPs, JavaServer Pages, make use of JavaBeans in this way. Values returned from an HTML form are set as properties, which can later be retrieved for some processing.

Normally, all public methods are exported. If bean providers want to limit the number of properties, events, and methods exported, they can supply a class that implements the BeanInfo interface. The BeanInfo interface defines methods for other objects to easily query what members and events are available. The code that determines which methods are exported is in the implementation of BeanInfo.

A bean can provide its own PropertyEditor for new data types, allowing the bean to be included in a visual component environment. Such an editor can either support Strings as values, or it may even use its own

java.awt.Component to do the editing.

When the bean can provide its own customizer for more complex customization, that type of editor should extend from java.awt.Component and implement java.beans.Customizer so that a graphical editor can integrate the editor in the GUI.

A JavaBean needs to support some way of persisting itself, so it has to either implement java.io.Serializable or java.io.Externalizable. When the bean is persisted, its internal state should be saved so that the bean may later be restored with the same data. This serialized version of a bean can even be treated as its own type. The java.beans.Beans.instantiate method takes several arguments, one of which is the name of a Bean as a String. The instantiate method first tries to locate a file with the specified name with a trailing .ser; if that fails, it tries to locate a class with the bean name and, if found, instantiate that.

186

Pattern Use
Factory Method (see page 21): In JavaBeans, the Factory Method is used to instantiate beans through the Beans.instantiate method and to abstract the real creation of the object. The caller of the method sees no difference between whether the bean has been restored from serialization or that a new object has been created—making it easier to reuse beans. A customizer only has to change some properties to let the bean appear as a different type, serialize the bean, and give it a name with the . ser extension.
Singleton (see page 34): Applications use the Introspector to find information about a Bean. The Introspector provides information about what methods, events, and properties a bean instance supports. It traverses the inheritance tree and looks for implicit and explicit information to use in building a BeanInfo object. Only one Introspector is needed to provide this functionality. To prevent redundancy, only a single instance is used so it can cache information for other requests.
Adapter (see page 142): The Adapter is specifically mentioned in the JavaBeans Specification ([JBS] although there it is called Adaptor). The task of the Adapter is to decouple the event source from the actual listeners and perform one or more of the following tasks:
Implement a queue for the incoming events so that events may be searched in the situation where a specific event in a series of events is missed.
Provide a filter to prevent all events from arriving at the actual target, letting only those events pass that fulfill certain criteria. You could set up an Adapter between a temperature bean and a warning bean and only forward the change events if the temperature changes more that 0.1 degrees Celsius instead of just every minuscule change.
Demultiplexing. A class can implement a specific method from an interface only once. If the same object is going to listen to multiple sources of the same event, but the reaction should be different based on the source, the implementation of the listener method has to change for every new source and the method will become bloated with large switch statements. Here the Adapter pattern is used to demultiplex. That means an Adapter instance is created for every event source and that instance is registered with the source. When the listener method gets called, the Adapter invokes another method on the actual listener, a different method for each different source. Now the actual listener no longer needs to determine where the event came from. That is the responsibility of the adapter.
Connect a source and a listener. This is useful when the event source and actual listener are of different event types. Its functionality is essentially that of the “true” Adapter , as described in the Adapter pattern.

Observer (see page 94): JavaBeans provides support for bound and constrained properties in beans.

Bound properties mean that beans can be connected together, and when a bound property changes, all interested beans are notified. These properties are called bound because they allow other classes and objects to bind behavior to the changes of the property.

The bound property acts as the Observable and the beans interested in the changes are the Observers to that

property. They are registered through the method addPropertyChangeListener( PropertyChangeListener

listener) and must implement the PropertyChangeListener interface .

When the property change occurs a PropertyChangeEvent is created with, among others, the old and new values and the propertyChange method is called on the listeners passing the PropertyChangeEvent as the argument.

Constrained properties are a variation on this principle, the difference is that the listeners may throw a PropertyVetoException if the listener objects to the change from the old to the new value. The listeners are

registered through the method addVetoableChangeListener( VetoableChangeListener listener) and they

must implement the VetoableChangeListener interface. The bean where the property change occurs calls the vetoableChange method on the registered listeners passing a PropertyChangeEvent as the argument. If a PropertyVetoException occurs, the same bean will undo the change and call the same listeners but with a PropertyChangeEvent that has reversed the new and old values, effectively rolling back the previous change.

187