Personality Pattern
by Luis Blando/Karl Lieberherr/Mira Mezini

Intent
 - Describe popular behavior independent of class structure.
 - Define the skeleton of an algorithm or a role deferring some steps
to abstract methods.
 - Turn roles on and off dynamically.

Motivation
 - Have an encapsulated unit for behavioral abstraction.
 - Distinguish between "IS-A" and "PLAYS-THE-ROLE-OF" relationships.

Applicability
 - Use to implement popular behaviors.
 - Whenever you have a class hierarchy (IS-A) and a behavior hierarchy
(PLAYS-THE-ROLE-OF) that do not conform to each other.

Structure
 - A personality  has local data and functions and
a constructor and a public upstream and private downstream interface.
 - A personality provides an implementation for a set of
functions (the upstream interface) that modify classes
that implement the downstream interface of the personality.
 - A personifying class implements the functions defined
in the downstream interface.
 - A personifying class can personify multiple personalities
at the same time, while it can inherit from only one class.
 - A client of the personalized class can only use the functions
in the upstream interface of the personality.
 - A personality's upstream interface functions follow the
Template Method Pattern.
 - A personality must conform to the Law of Personalities (LoP) which
requires the following:
    1. The downstream interface must be a set of pure abstract functions.
    2. Clients of the personality must not use the links to the
personifying class (i.e. the downstream interface).
    3. The implementation of the popular functions must be protected
against changes by the personifying classes.
    4. The implementation of popular functions is allowed to use the
DI/UI/local methods and the methods
of classes returned by the DI/UI/local methods and
nothing more. This includes methods of classes of local data and of return
types. This is analogous to the Law of Demeter in [1].


Examples:
 - A sample personality definition follows:
  // Flier.pj
  personality Flier {
    // upstream interface. Must implement here.
    public void Fly(int x, int y, int altitude) {
      resetMetersFlown();
      Takeoff();
      for (int a=0; a < altitude; a++) Ascend();
      while( !ThereYet(x, y) ) FlapTowards(x, y);
      for(int a = altitude; a > 0; a--) Descend();
      Land();
    }
    // downstream interface. Don't impl here.
    di void Takeoff();
    di void Ascend();
    di boolean ThereYet(int x, int y);
    di void FlapTowards(int x, int y);
    di void Descend();
    di void Land();
    // private functions. Must implement here.
    private void resetMetersFlown() { meters_flown = 0; }
    // attributes (specific to the role)
    private float meters_flown;
    // constructor (optional)
    Flier() { resetMetersFlown(); }
  }

 - A sample personifying class using the above personality
follows:
  // Bat.pj
  public class Bat
   extends Mammal
   personifies Flier
  {
    // di implementation for Flier ------------------------
    void Takeoff() { trace("Bat.Takeoff():"); }
    void Ascend() { trace("Bat.Ascend()");  }
    boolean ThereYet(int x, int y) {
      trace( "Bat.ThereYet()" );
      return true;
    }
    void FlapTowards(int x, int y) { trace( "Bat.FlapTowards()" ); }
    void Descend() { trace( "Bat.Descend():" ); }
    void Land() { trace( "Bat.Land()" ); }
  }



Implementation
 - Personalities are implemented by using delegation. One $Ego
class is created for each personality defined (i.e., Flier$Ego).
 - Popular behavior implementation is placed there. A class
gets one instance of the appropriate $Ego object when
personifying a personality. Proxy methods for the upstream
interface implementation are automatically generated that
delegate to those in the $Ego object.

 - The Flier$Ego.java class, generated from Flier.pj, follows:
/***************************************************************
  [ Flier$Ego.java ]
  Automatically generated by Personalities/Java compiler.
  ***************************************************************/
public class Flier$Ego
{
  public Flier$Ego()
  {
    resetMetersFlown();
  }
  public void Fly(Flier host, int x, int y, int altitude)
  {
    resetMetersFlown();
    host.Takeoff();
    for(int a=0;a0;a--)
      host.Descend();host.Land();}
  private void resetMetersFlown(){
    meters_flown=0;}
  private float meters_flown;
}



 - The Bat.java class, generated from Bat.pj, follows:
/***************************************************************
  [ Bat.java ]
  Automatically generated by Personalities/Java compiler.
  ***************************************************************/
public class Bat extends Mammal  implements Flier
{
  public void Takeoff(){
    trace("Bat.Takeoff():");}
  public void Ascend(){
    trace("Bat.Ascend()");}
  public boolean ThereYet(int x,int y){
    trace("Bat.ThereYet()");return true;
  }
  public void FlapTowards(int x,int y){
    trace("Bat.FlapTowards()");}
  public void Descend(){
    trace("Bat.Descend():");}
  public void Land(){
    trace("Bat.Land()");}
  Flier$Ego $flier = new Flier$Ego();
  public void Fly(int x,int y,int altitude)
  {
    $flier.Fly( this, x, y, altitude);
  }
}

Related Pattern:
Template Method (GOF)

Connection to APPC:
http://www.ccs.neu.edu/research/demeter/biblio/components.html

An APPC is a personality with built-in framework for implementing 
down-stream interface.

For More Information
 - Visit http://www.ccs.neu.edu/research/demeter/personalities/
for more details on Personalities and their implementation

References
 [1] Lieberherr, K. Adaptive Object-Oriented Software: The Demeter Method
with Propagation Patterns. PWS Publishing Company, Boston, 1996.