Hi Luis: From your email address I conclude that you are already at MIT. I wish you a successful start in your new endeavour. Your example and the implementation description is very good. I made some small changes below and left a question after KJL. I think that the LoP is also part of the pattern. Belongs into the structure part. We should add the LoD for personalities from my earlier message: inside a personality we can only use a limited set of functions. -- Karl From lblando@mit.edu Tue Dec 29 12:15:34 1998 Reply-To: From: "Luis Blando" To: "Karl Lieberherr" , Subject: RE: FW: Form mail from Date: Tue, 29 Dec 1998 12:15:50 -0500 This is a multi-part message in MIME format. ------=_NextPart_000_0006_01BE3324.F9437720 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit > Any progress on the Personality Pattern? I am attaching a first version of such a pattern. Please send me your comments, suggestions, additions. Luis ------ Luis Blando, PMTS 781.466.3296 (v) lblando@mit.edu OSL, GTE Laboratories 781.466.2941 (f) lblando@labs.gte.com Waltham, MA 02451 800.971.4118 (p) http://www.mit.edu/~lblando ------=_NextPart_000_0006_01BE3324.F9437720 Content-Type: text/plain; name="pers-pattern.txt" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="pers-pattern.txt" Personality Pattern 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 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 { //initializers below //nested classes below //constructor below //PersonalityConstructorDecl(0) KJL: What is (O)? public Flier$Ego() { resetMetersFlown(); } //[methods body begins.] //PersonalityMethodDecl(0) UI = public public void Fly(Flier host, int x, int y, int altitude) { resetMetersFlown(); host.Takeoff(); for(int a=0;a0;a--) host.Descend();host.Land();} //PersonalityMethodDecl(1) -private or protected- private void resetMetersFlown(){ meters_flown=0;} //[methods body ends.] //fields below //PersonalityFieldDecl(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 { //initializers: 0 //constructors: 0 //nested class: 0 //nested init : 0 //methods : 6 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()");} //fields : 0 //UI methods for 1 personalities //for personality Flier : Flier$Ego $flier = new Flier$Ego(); public void Fly(int x,int y,int altitude) { $flier.Fly( this, x, y, altitude); } } For More Information Visit http://www.ccs.neu.edu/home/lblando/personalities for more details on Personalities and their implementation ------=_NextPart_000_0006_01BE3324.F9437720--