uml for java developers - engr.sjsu.edu · uml and java are not directly equivalent, and in some...

25
1 Copyright Jason Gorman 2003 1 UML for Java Developers Class Diagrams

Upload: others

Post on 22-Oct-2020

8 views

Category:

Documents


0 download

TRANSCRIPT

  • 1

    Copyright Jason Gorman 2003 1

    UML for Java Developers

    Class Diagrams

  • 2

    Copyright Jason Gorman 2003 2

    Classes

    A ccount class Account{}

    class Account{}

    In UML class di agrams, a cl ass is represented by a rect angle with one or more compartments. The topmost (and always mandatory) compartment contains the name of the class. The same cl ass can only appear on any class di agram once.

  • 3

    Copyright Jason Gorman 2003 3

    Attributes

    A ccount

    class Account{

    private float balance = 0;private float limit;

    }

    class Account{

    private float balance = 0;private float limit;

    }- balance : S ingle = 0- limit : S ingle

    [v isibility ] [/] att ribute_name[mult iplicity ] [: ty pe [= default_v alue]]

    Attribut es correspond to the variables decl ared within a cl ass (but not vari ables declared within the body of a function or sub procedure).

    Here are some more examples of UML attribute decl arations and the equivalent Java code:

    -- att ribute with multiplicity of 1 or more.

    - names[1..*] : String = {“ Jason”, “ Gorman”}

    private String[] names = new String[]{"Jason", "Gorman"};

    -- derived att ribute (denoted by “ /” before attribute name. Derived attribut es can be implemented as functions that calcul ate the value when requested, or an att ribute that is updat ed whenever factors change (oft en for performance reasons where it would be too costly to recal culat e every time the value is needed. )

    -/ availabl eFunds = bal ance + limit

    privat e float availableFunds(){

    return balance + limit;}

    --attribut e with enumerated values

    - colour : enum{RED, BLUE, GREEN}

  • 4

    Copyright Jason Gorman 2003 4

    OperationsA ccount

    class Account{

    private float balance = 0;private float limit;public void deposit(float amount){

    balance = balance + amount;}

    public void withdraw(float amount){

    balance = balance - amount;}

    }

    class Account{

    private float balance = 0;private float limit;public void deposit(float amount){

    balance = balance + amount;}

    public void withdraw(float amount){

    balance = balance - amount;}

    }

    - balance : S ingle = 0- limit : S ingle+ deposit(amount : S ingle)+ w ithdraw(amount : S ingle)

    [v isibility ] op_name([[in|out] parameter : ty pe[, more params]])[: return_ty pe]

    Operations correspond to functions or sub procedures in Java. To help you get a feel for operation declarations, here are some more examples with equival ent Java decl arations:

    + walk(direction : CompassBearing, distance : float)

    public void walk(CompassBearing direction, float distance)

    execute(arguments [0..*] : object ) : Response

    Response execute(object []arguments)

    + setName(String)

    public void setName(String value)

  • 5

    Copyright Jason Gorman 2003 5

    Visibility

    A ccount- balance : float = 0+ limit : float# id : int~ databaseId : int+ deposit(amount : single )-w ithdraw(amount : single)# getAvailableFunds() : single~ getDatabaseId() : int

    + = public- = private# = protected~ = package

    class Account{

    private float balance = 0;public float limit;protected int id;int databaseId;

    public void deposit(float amount){

    balance = balance + amount;}

    private void withdraw(float amount){

    balance = balance - amount;}

    protected int getId(){

    return id;}

    int getDatabaseId(){

    return databaseId;}

    }

    class Account{

    private float balance = 0;public float limit;protected int id;int databaseId;

    public void deposit(float amount){

    balance = balance + amount;}

    private void withdraw(float amount){

    balance = balance - amount;}

    protected int getId(){

    return id;}

    int getDatabaseId(){

    return databaseId;}

    }

    Public members (attribut es or operations) can be referenced directly by any cl asses in this or any other model package (more on packages l ater).

    Private members can only be referenced in the same class where they’re decl ared.

    Protected members can be referenced in the same cl ass or in any descendants of that cl ass (more on inheritance later).

    Package scope members can be referenced by any cl asses in the same UML package only.

  • 6

    Copyright Jason Gorman 2003 6

    Class & Instance Scope

    Person- numberOfPeople : int- name : string+ createPerson(name : string) : Person+ getName() : string+ getNumberOfPeople() : int- Person(name : string)

    class Person{

    private static int numberOfPeople = 0;private String name;

    private Person(string name){

    this.name = name;numberOfPeople++;

    }

    public static Person createPerson(string name){

    return new Person(name);}

    public string getName(){

    return this.name;}

    public static int getNumberOfPeople(){

    return numberOfPeople;}

    }

    class Person{

    private static int numberOfPeople = 0;private String name;

    private Person(string name){

    this.name = name;numberOfPeople++;

    }

    public static Person createPerson(string name){

    return new Person(name);}

    public string getName(){

    return this.name;}

    public static int getNumberOfPeople(){

    return numberOfPeople;}

    }

    int noOfPeople = Person.getNumberOfPeople();Person p = Person.createPerson("Jason Gorman");

    int noOfPeople = Person.getNumberOfPeople();Person p = Person.createPerson("Jason Gorman");

    Class scope members can be referenced without instanti ating the class to which they belong. They are essentially shared for the entire system – in Java they are decl ared as static members.

    In UML, class scope members are underlined. If a member is not cl ass scope, then it can only be appli ed to a single inst ance of that class – which we call an instance scope (or just”inst ance”) member.

    In this example, we have a class attribut e called numberOfPeople that records the tot al number of all instances of P erson. The class operation createPerson() is used to create inst ances of P erson, and Person objects cannot be creat ed any other way because it has a privat e constructor that only Person can call.

    [You’ll notice that the Assert () operation of the Debug class is also a cl ass operation because we did not have to creat e an instance of Debug to call it.]

  • 7

    Copyright Jason Gorman 2003 7

    Associations

    A B1b

    multiplicity

    role name

    Ab : B

    Equivalent to

    class A{

    public B b = new B();}

    class B{}

    class A{

    public B b = new B();}

    class B{}

    A a = new A();B b = a.b;

    A a = new A();B b = a.b;

    1

    There are a number of ways in which cl asses can be rel ated to each other. Arguably the simplest kind of relationship is an association. A has an associ ation with B whereby inst ances of A always have a reference to exactly one instance of B. The name of this reference is b. The role played by B in this relationship has the name b, and multipli city 1.

    The arrowhead at B’s end of the associ ation tells us that the associ ation is navigable only in the di rection A->B. In code, this means that instances of A hold a reference to instances of B, but not vice-versa.

    The code sample:

    A a = new A();B b = a.b;

    Would be valid because we can navigate to the role b in this rel ationship. There is no way to navigat e from B to A, so the code snippet:

    B b = new B();A a = b.a;

    Would not be valid. In UML, as in OO programming, we navigate along associ ations using the role/ reference name.

  • 8

    Copyright Jason Gorman 2003 8

    Bi-directional AssociationsA

    b : BEquivalent to

    class A{

    public B b;public A(){

    b = new B(this);}

    }

    class B{

    public A a;public B(A a){

    this.a = a;}

    }

    class A{

    public B b;public A(){

    b = new B(this);}

    }

    class B{

    public A a;public B(A a){

    this.a = a;}

    }

    A a = new A();B b = a.b;A a1 = b.a;assert a == a1;

    A a = new A();B b = a.b;A a1 = b.a;assert a == a1;

    Ba : A

    A B1b

    multiplicity

    role namea1

    In the previous example, the association between A and B was only navigable in one direction – from A to B. In this example, the associ ation is navigable in both directions.

    An associ ation that is only navigable in one direction is call ed unidirectional. An association that is navigable in both directions is called bi-directional.

  • 9

    Copyright Jason Gorman 2003 9

    Association names & role defaults

    Person AddressLives at

    Default role name = addressDefault multiplicity = 1

    class Person{

    // assoc iation : Lives atpublic A ddress address;

    public Person(A ddress address){

    this.address = address ;}

    }

    class Person{

    // assoc iation : Lives atpublic A ddress address;

    public Person(A ddress address){

    this.address = address ;}

    }

    In UML, we can optionally give associations names to help identi fy which associ ation we are t alking about. Sometimes the direction of the associ ation is shown as an arrowhead aft er the name.

    Association names have no direct equivalent in Java. You may choose to record the associ ation name as comments in the code to show that one or more object references play a rol e in that particul ar association.

    If no explicit rol e name is given at an associ ation end, the default rol e name impli ed is the name of the cl ass at that end (in this case, Address ) beginning with a lowercase letter – address.

    If no explicit multiplicity for a rol e is given, the default mul tiplicity is implied as 1.

  • 10

    Copyright Jason Gorman 2003 10

    Multiplicity & CollectionsCustomer Account1..*

    accounts

    class Customer{

    // accounts[1..*] : AccountArrayList accounts = new ArrayList();

    public Customer(){

    Account defaultAccount = new Account();accounts.add(defaultAccount);

    }}

    class Customer{

    // accounts[1..*] : AccountArrayList accounts = new ArrayList();

    public Customer(){

    Account defaultAccount = new Account();accounts.add(defaultAccount);

    }}

    Customeraccounts[1..*] : Account

    Equivalent to

    1..2

    When a role in an association has a multiplicity greater than 1, it cannot be implemented with a single reference to an object of that type. Java offers a range of di fferent kinds of coll ection class, many found in the namespace j ava.util. We use collections to implement roles with a multiplicity great er than 1.

    Care must be taken when implementing rol es as collections, though. It is not immediat ely obvious to anyone looking at the code in this example that accounts is definitely a collection of Account objects, or that the lower range of the multiplicity of the role accounts is 1. This is only implied if you read the constructor code, which makes it impossible to instanti ate a Customer without at least one Account – the default account.

    Generally, associ ation rul es (like multiplicity bounds) are implemented in code such that it is not possible to break those rul es –or at least an exception is thrown when the rul es are broken.

    Starting with the code and working back to a class di agram, one must make sensibl e choices about how to represent associations with multiplicity great er than one, since the code itsel f does not make it expli cit what the intention was in the programmer’s mind. This is one of the weaknesses in the model-driven approach to software development. UML and Java are not directly equival ent, and in some pl aces their relationship is ambiguous and open to interpret ation. Developers may wish to define standard mappings within their team or department (or ent erprise) so that such relationships are always interpret ed in the same way. Developers may also choose to use structured comments to capture model information in code so that thei r intention is clearly communicat ed.

  • 11

    Copyright Jason Gorman 2003 11

    Aggregation & CompositionC omputer HardwareDev ice

    1..*

    Aggregation – is made up o f objects that can be shared or exchanged

    ShoppingBasket O rderItem1..*

    Composition – is composed of objects that cannot be shared or exchanged and live only as long as the composite object

    0..1

    1

    Arguably, aggregation relationships have no direct equival ent in Java. They are essenti ally an analysis concept that conveys the way in which one object can be built up of other objects. For example, a computer can be built up of hardware devices. Sound cards, video adaptors and hard drives can be taken out of one computer and insert ed into another. This means that they can live without the computer to which they originally belonged.

    A shopping basket on an e-commerce web site will likely be made up of order items that users can add during their session and then submit at the end. The order items cannot exist without that speci fi c shopping basket to which they belong. We model a rel ationship where one object is composed of other obj ects, and these objects only live as long as the composit e object, using a composition rel ationship. In Java, this means enforcing a rul e such that no other objects share references to the order items, and when the shopping basket is is destroyed (made avail able for garbage collection), all its order items are dest royed with it.

  • 12

    Copyright Jason Gorman 2003 12

    GeneralizationPerson

    Employ ee

    class Person{}

    class Employee extends Person{}

    class Person{}

    class Employee extends Person{}

    A generali zation rel ationship between two cl asses means that one cl ass inherits the att ributes and operations of another. In this example, we are saying that an Employee is a kind of Person.

  • 13

    Copyright Jason Gorman 2003 13

    Realization

    Person

    Employ ee Employ ee

    Person

    OR

    interface Person{}

    class Employee implements Person{}

    interface Person{}

    class Employee implements Person{}

    A realization rel ationship shows that one class implements the interface of another cl ass (with stereotype - more about stereotypes later). There are two possibl e notations you could use to represent a reali zation rel ationship – one most likely a hangover from the days of C OM…

    Remember that in Java, classes can implement multiple interfaces but cannot inherit from multiple classes – an ability usually call ed multipl e inheritance. Java does not support multiple inherit ance.

  • 14

    Copyright Jason Gorman 2003 14

    Overriding Operations

    Account

    + depo sit(amount : float)+ withdraw(amount : float)

    SettlementAccount

    + withdraw(amount : float)

    -debt : float = 0/ availableFunds : flo at = balance + limit - deb t

    # balance : flo at = 0# limit : float = 0

    class Account{

    protected float balance = 0;protected float limit = 0;public void deposit(float amount){

    balance = balance + amount;}public void withdraw(float amount){

    balance = balance - amount;}

    }class SettlementAccount extends Account{

    private float debt = 0;float availableFunds(){

    return (balance + limit -debt);}public void withdraw(float amount){

    if (amount > this.availableFunds()){

    throw new InsufficientFundsException();}base.withdraw(amount);

    }}

    class Account{

    protected float balance = 0;protected float limit = 0;public void deposit(float amount){

    balance = balance + amount;}public void withdraw(float amount){

    balance = balance - amount;}

    }class SettlementAccount extends Account{

    private float debt = 0;float availableFunds(){

    return (balance + limit -debt);}public void withdraw(float amount){

    if (amount > this.availableFunds()){

    throw new InsufficientFundsException();}base.withdraw(amount);

    }}

    When one cl ass inherits the implementation of another cl ass, it inherits all of the implementations of its operations (t he implementation of an operation is called a method ). There will be occasions, however, when you will want to change the implementation of an operation in the subcl ass by overriding it. In this example, we’ve overridden the withdraw() operation’s implementation to throw an exception i f the account has insuffici ent funds for the transaction.

    In UML, an overridden operation appears in the operations compartment of the subcl ass to show that it has a di fferent implementation.

  • 15

    Copyright Jason Gorman 2003 15

    Abstract Classes & Abstract Operations

    Account+ deposit(amount : float)+ withdraw(amount : float)

    SettlementAccount

    + deposit(amount : float)+ withdraw(amount : float)

    - balance : float = 0- limit : float = 0- debt : float = 0/ availableFunds : float = balance + limit - debt

    abstract class Account{

    public ab stract vo id deposi t(float amount) ;public ab stract vo id w ithdraw(floa t amount);

    }

    class Set tlementAccoun t extends Accoun t{

    private float balance = 0;private float limit = 0;private float debt = 0 ;float availab leFunds(){

    return (balance + limit - debt);}public void depos it(float amount){

    balance = balance + amount;}public void withdraw(float amoun t){

    if (amount > this.availab leFunds()){

    throw new InsufficientFundsException();}balance = balance - amount;}

    }

    abstract class Account{

    public ab stract vo id deposi t(float amount) ;public ab stract vo id w ithdraw(floa t amount);

    }

    class Set tlementAccoun t extends Accoun t{

    private float balance = 0;private float limit = 0;private float debt = 0 ;float availab leFunds(){

    return (balance + limit - debt);}public void depos it(float amount){

    balance = balance + amount;}public void withdraw(float amoun t){

    if (amount > this.availab leFunds()){

    throw new InsufficientFundsException();}balance = balance - amount;}

    }

    Sometimes we want to create an ext endable cl ass, but we don’t want to be abl e to instantiat e that cl ass directly. Sometimes you may wish to share some functionality or attribut es between a family of cl asses – which we could do by creating a base cl ass from which all the members of the family inherit. It may not make sense, however, to treat the base class as a kindof object in its own right. You want to be able to ext end it, but you don’t want to be abl e to create inst ances of the base class directly. Perhaps you want a class that provides only a partial implementation that other classes can extend.

    Partially implemented classes can be made abstract, which forces us to extend it before we can use its functionality. In cl ass diagrams, the name of an abstract class can be written in italics, or {abstract} is written above it in the class name compartment.

    You may also wish to define abst ract operations that must be implemented in subclasses of the abst ract cl ass. Again, an abstract operation appears in italics on UML cl ass diagrams.

  • 16

    Copyright Jason Gorman 2003 16

    More on GeneralizationA

    DCB

    A

    DCB

    Equivalent to

    {abstract}Mammal

    BirdC atHuman

    Mammal

    BirdC atHuman

    Equivalent to

  • 17

    Copyright Jason Gorman 2003 17

    Dependencies – C#

    Account

    InsufficientFundsException

    + withdraw(amount : float)

    public class Account {

    public void withdraw(float amount) throws InsufficientFunds Exception{

    }}

    public class Account {

    public void withdraw(float amount) throws InsufficientFunds Exception{

    }}

    Sometimes you will wish to show that, although two cl asses are not relat ed by associ ation, aggregation or composition, they are still in some way dependant on each other.

    For example, the method withdraw() can throw an Insuffi ci entFundsException.

  • 18

    Copyright Jason Gorman 2003 18

    Qualified Associations

    Library Title

    0..*0..1ISBN

    0..*

    item0..*

    class Library{

    private HashMap titles = new HashMap();

    public Title item(String isbn){

    return (Title)titles.get(is bn);}

    }

    class Library{

    private HashMap titles = new HashMap();

    public Title item(String isbn){

    return (Title)titles.get(is bn);}

    }

    It is oft en useful to be able to navigat e to a speci fi c obj ect – or a subset of objects - at one end of an association with a multiplicity great er than one. In UML, we can use a quali fi er to achieve this. A quali fi er is one or more parameters that can beused to speci fy a subset of objects in an associ ation.

    In our simple example, we use the ISBN of book titles to navigat e to a speci fi c title. In Java, we’ve chosen to implement the titles collection as java.util.Hashmap, which allows to associ ate a unique key - the ISBN – with a speci fi c instance of Title.

    If no Title exists with that ISBN, navigating to item returns no Title, so the lower bound of the multiplicity is 0. A library never has the same Title twice in this example.

  • 19

    Copyright Jason Gorman 2003 19

    Association Classes

    Customer Video

    RentaldateRented : DateTime

    0..1 0..*

    class Customer{

    ArrayList rentals = new ArrayList();}class Video{

    Rental rental;}class Rental{

    Customer customer;Video video;

    DateTime dateRented;

    public Rental(DateTime dateRented, Customer customer, Video video)

    {this.dateRented = dateRented;video.rental = this;customer.rentals.add(this);this.customer = customer;this.video = video;

    }}

    class Customer{

    ArrayList rentals = new ArrayList();}class Video{

    Rental rental;}class Rental{

    Customer customer;Video video;

    DateTime dateRented;

    public Rental(DateTime dateRented, Customer customer, Video video)

    {this.dateRented = dateRented;video.rental = this;customer.rentals.add(this);this.customer = customer;this.video = video;

    }}

    + Rental(DateTime, Customer, Video)

    Occasionally you will want to capture information about an associ ation that goes beyond rol e names, visibility, scope, const raints or multiplicity. An association class can be used to model information about associ ations. In Java, association classes have no di rect equival ent – they are enti rely an analysis concept. We can, however, approximate them by creating a two-st ep relationship that allows us to navigate from Customer to Rental, and from Rental to Video. Customer has no direct rel ationship with Video, and Video has no di rect relationship with Customer.

  • 20

    Copyright Jason Gorman 2003 20

    Associations, Visibility & ScopeLibrary Title

    0..*0..*- titles

    class Library{

    private Title[] ti tles;

    }

    class Library{

    private Title[] ti tles;

    }

    Team Person2..*

    # members

    class Team{

    protected Person[] members;}

    class Team{

    protected Person[] members;}

    Customer0..*- allInstances

    class Customer{

    private stat ic Customer[] allIns tances;}

    class Customer{

    private stat ic Customer[] allIns tances;}

    Just as you can speci fy the visibility and scope of att ributes in cl ass diagrams, you can also speci fy the visibility and scope of association ends using the same modi fi ers:

    1. + = public2. - = privat e3. # = protect ed4. ~ = package

    Underlining the rol e name tells us that the association end has class scope rather than inst ance scope.

    Although we have seen many examples in this presentation of publi cly visible associ ation ends, in practice the principl e of information hiding – that is, only allowing clients access to dat a (including references to other objects) through well -defined int erfaces – means one should only ever speci fy association ends as private or prot ect ed in det ailed t echnical designs.

  • 21

    Copyright Jason Gorman 2003 21

    Information Hiding – Wrong!

    Personname : string parents0..2

    childr en0..*

    class Person{

    public String name;

    public Parent[] parents = new Parent[2];

    public ArrayList c hildren = new ArrayList();

    }

    class Person{

    public String name;

    public Parent[] parents = new Parent[2];

    public ArrayList c hildren = new ArrayList();

    }

    Person mary = new Person();Person ken = new Person();Person jason = new Person();jason.parents[0] = mary ;jason.parents[1] = ken;mary .children.add(jason);ken.ch ildren.add(jason);jason.name = "Jason";

    Person mary = new Person();Person ken = new Person();Person jason = new Person();jason.parents[0] = mary ;jason.parents[1] = ken;mary .children.add(jason);ken.ch ildren.add(jason);jason.name = "Jason";

    The wrong way to do things is to make attributes and associ ations ends public and allow the cli ent to manipulat e or access them directly.

  • 22

    Copyright Jason Gorman 2003 22

    Information – Right!

    Person- name : str ing - parents0..2

    - children 0..*

    Person mary = new Person();Person ken = new Person();Person jason = new Person(mary, ken);

    jason.setName("Jason");

    Person mary = new Person();Person ken = new Person();Person jason = new Person(mary, ken);

    jason.setName("Jason");

    class Person{

    private String name;private Parent[] parents = new Parent[2];private ArrayList children = new ArrayList();

    public Person(Person mother, Person father){

    this.setParent(0, mother);this.setParent(1, father);

    }public void setName(String value){

    this.name = value;}public void setParent(int index, Person parent){

    parents[index] = parent;parent.addChild(this);

    }public void addChild(Person child){

    this.children.add(child);}public Person(){}

    }

    class Person{

    private String name;private Parent[] parents = new Parent[2];private ArrayList children = new ArrayList();

    public Person(Person mother, Person father){

    this.setParent(0, mother);this.setParent(1, father);

    }public void setName(String value){

    this.name = value;}public void setParent(int index, Person parent){

    parents[index] = parent;parent.addChild(this);

    }public void addChild(Person child){

    this.children.add(child);}public Person(){}

    }

    + Per son(mo ther : P erson, father : Per son)+ Per son()+ setName(value :str ing)+ setParen t(index : in t, p arent : Per son)+ addChild(child : Person)

    The right way to do it is to use public operations so that Person manipulates its own att ributes and associ ation ends. This greatly simpli fi es the cli ent’s job, and makes it easy to change the way Person works (eg, replacing the Parent[] array with an ArrayList) without any impact on any code that uses Parent objects.

    Generally, the less one cl ass knows about another, the bett er.

  • 23

    Copyright Jason Gorman 2003 23

    Exercise #1 - BeginnerBook

    # title : String = “”;- author : String~ published : Date- comments[0..*] : string+ createBook(title : st ring, author : st ring, published : DateTime) : Book- setTitle(v alue : string)+ addC omment(comment : string)

    Write the Java code to implement the class diagram exactly as you see it above

    Java:

    abstract class Book{

    protect ed String title = “ ”;privat e String author;Date published = Date.Now;privat e ArrayList comments;

    public stati c Book creat eBook(String title, String author, Date published){}

    privat e void setTitle(String value){}

    public abstract void addComment (String comment );

    }

  • 24

    Copyright Jason Gorman 2003 24

    Exercise #2 - Intermediate

    A

    B C

    I

    D0..*

    0..1

    1..*

    1

    Write the Java code to implement the class diagram exactly as you see it above

    Java:

    interface I{}

    abstract class A implements I{

    // default role name is Classi fier starting with lowercase lett erD[] d;

    }

    class B ext ends A{}

    class C ext ends A{

    D d;}

    class D{

    C[] c;

  • 25

    Copyright Jason Gorman 2003 25

    Exercise #3 - AdvancedA

    + doStuff()

    B+ doStuff() C

    D

    0..1

    1

    + theC

    key : string

    0..*1- cs

    Write the Java code to implement the class diagram exactly as you see it above

    * ~ children

    0..1