Introduce Role Objects

Purpose

to refactor roles implemented as subclasses of a role player class in such a way that it is easy to let instances of the role classes ("role objects") share state and identity with an instance of the role player class

System requirements

Rationale

It is common practice to implement roles such as Employee, Customer, etc. as subclasses of a common role player class such as Person. However, this means that different instances of the role classes are actually different objects with different state and different identity, even if they are meant to represent the same logical entity. The Role Object Pattern (ROP) addresses this problem by representing an object and its roles as a composition of one role player object (called the core) and arbitrarily many role objects. The static structure of the pattern is specified by the following UML class diagram:

However, in order to be behaviour preserving introduction of the ROP requires true delegation among the roles and their core, a construct that is usually not available in class-based object-oriented programming languages and whose emulation requires quite a bit of extra code (see our Replace Inheritance with Delegation Refactoring). Although all the necessary code is introduced by our refactoring tool, the resulting programs are difficult to understand and maintain. We have therefore developed a significantly simpler variant of the ROP, which we have called Lightweight Role Objects (LRO) and whose structure is given by the following class diagram:

As can be seen, the inheritance structure of the original program is maintained, and with it the natural implementation of delegation (as inheritance).

Our refactoring tool offers both alternative implementations of role objects.

Usage

After installation, the refactoring is ready for use. Simply open the context menu on a class in the Package Explorer of an Eclipse workspace, in the Outline view of a compilation unit, or on a selected class name in an editor, and select Introduce Role Object > Role Object Pattern or > Lightweight Role Objects.

In the screen that follows, you can enter the names of program elements introduced by the refactoring (here shown for the Role Object Pattern).

After having made your choice, you should preview the changes performed by the refactoring.

Nota bene: The refactoring is a refactoring and therefore does not change the meaning of the program. In order to leverage role objects, you have to change your code to invoke the addRole factory method introduced by the refactoring for creating role instances that are to share state and identity with a core (or entity). For instance, instead of writing

Employee e = new Employee();

you now have to write

Person p = new PersonCore();
Employee e = p.addRole(Employee.class);

This however can change the meaning of the program (this in Person now points to a different object than this in Employee) and can therefore not be performed as part of the refactoring.

Installation

Copy this jar into Eclipse’s plugin directory and restart Eclipse.

Publications

Team


The intoJ Team, 2010.