© 1999-2009, Flemming Koch Jensen
Alle rettigheder forbeholdt
Komposition

Vejledende løsninger

 

 

1

Først laver vi Regner med set-konstruktor og metoden f:

public class Regner {
  private double k;
  
  public Regner( double k ) {
    this.k = k;
  }
  
  public double f( double x ) {
    return k*x*x + 3;
  }
}
Konstanten k udgør datakernen, og alt laves med double.
Dernæst lave RegnerHandle:
public class RegnerHandle {
  private Regner objekt;
  
  public RegnerHandle( Regner objekt ) {
    setObjekt( objekt );
  }
  
  public double f( double x ) {
    return objekt.f( x );
  }
  
  public void setObjekt( Regner objekt ) {
    this.objekt = objekt;
  }
}

Datakernen er referencen til det objekt som handle repræsenterer.

Set-konstruktoren anvender set-metoden, og f delegerer blot opgaven videre til objektet.
Endelig har vi en testanvendelse, der udfylder de to roller: Opbygger af objektsystemet og klient-rollen.
public class Main {

  public static void main( String[] argv ) {
    // Opbygger objektsystem
    Regner k3 = new Regner( 3 );
    RegnerHandle ref = new RegnerHandle( k3 );
    
    // Klient
    System.out.println( ref.f( 4.0 ) );
    
    // Ændrer objektsystem
    Regner k5 = new Regner( 5 );
    ref.setObjekt( k5 );
    
    // Klient
    System.out.println( ref.f( 4.0 ) );
  }
}
51.0
83.0

 

2 Først laver vi klassen Bog, med set-konstruktor og de tre metoder: setPris, addAntal og subAntal:
 
public class Bog {
  private String titel;
  private String forfatter;
  private double pris;
  private int antal;
  
  public Bog( String titel, String forfatter, double pris, int antal ) {
    this.titel = titel;
    this.forfatter = forfatter;
    this.pris = pris;
    this.antal = antal;
  }
  
  public Bog( Bog other ) {
    this( other.titel, other.forfatter, other.pris, other.antal );
  }
  
  public void setPris( double pris ) {
    this.pris = pris;
  }
  
  public void addAntal( int antal ) {
    this.antal += antal;
  }
  
  public void subAntal( int antal ) {
    if ( this.antal - antal >= 0 )
      this.antal -= antal;
  }
  
  public String toString() {
    return "[" + titel + ", " + forfatter + ", " +
                 pris + " kr., antal: " + antal + "]";
  }
}
  Dernæst laver vi testanvendelsen med de to instanser af Bog. Vi kalder en række af metoderne med efterfølgende testudskrifter:
public class Main {
  
  public static void main( String[] argv ) {
    Bog deitel = new Bog( "Java: how to program", "Deitel & Deitel", 497.00, 8 );
    Bog horton = new Bog( "Beginning Java 2", "Ivor Horton", 495.00, 3 );
    
    System.out.println( deitel );
    System.out.println( horton );
    
    deitel.subAntal( 2 );
    System.out.println( deitel );
    
    horton.setPris( 395.00 );
    System.out.println( horton );
    
    horton.addAntal( 3 );
    System.out.println( horton );
  }
}
[Java: how to program, Deitel & Deitel, 497.0 kr., antal: 8]
[Beginning Java 2, Ivor Horton, 495.0 kr., antal: 3]
[Java: how to program, Deitel & Deitel, 497.0 kr., antal: 6]
[Beginning Java 2, Ivor Horton, 395.0 kr., antal: 3]
[Beginning Java 2, Ivor Horton, 395.0 kr., antal: 6]
  Handle-klassen laves dernæst:
 
public class BogHandle {
  private Bog bogen;
  
  public BogHandle( Bog bog ) {
    setObject( bog );
  }
  
  public void setObject( Bog bog ) {
    bogen = bog;
  }
  
  public void setPris( double pris ) {
    bogen.setPris( pris );
  }
  
  public void addAntal( int antal ) {
    bogen.addAntal( antal );
  }
  
  public void subAntal( int antal ) {
    bogen.subAntal( antal );
  }
  
  public String toString() {
    return bogen.toString();
  }
}
  I forbindelse med testanvendelsen bruger vi det samme handle-objekt for at illustrere muligheden for at udskifte det objekt som handle håndterer:
public class Main {
  
  public static void main( String[] argv ) {
    Bog horton = new Bog( "Beginning Java 2", "Ivor Horton", 495.00, 3 );

    BogHandle handle = new BogHandle( horton );
    System.out.println( handle );
    
    handle.addAntal( 8 );
    System.out.println( handle );
    
    Bog deitel = new Bog( "Java: how to program", "Deitel & Deitel", 497.00, 8 );
    
    handle.setObject( deitel );
    System.out.println( handle );

    handle.setPris( 299.00 );
    System.out.println( handle );
  }
}
[Beginning Java 2, Ivor Horton, 495.0 kr., antal: 3]
[Beginning Java 2, Ivor Horton, 495.0 kr., antal: 11]
[Java: how to program, Deitel & Deitel, 497.0 kr., antal: 8]
[Java: how to program, Deitel & Deitel, 299.0 kr., antal: 8]

 

3 Først laver vi Punkt.
public class Punkt {
  private double x, y;
  
  public Punkt( double x, double y ) {
    this.x = x;
    this.y = y;
  }
  
  public double getX() {
    return x;
  }
  
  public double getY() {
    return y;
  }
}
Da koordinatsystemet arbejder med R2, har vi valgt at bruge double.
Dernæst laver vi Linie:
public class Linie {
  private Punkt start, slut;
  
  public Linie( Punkt start, Punkt slut ) {
    this.start = start;
    this.slut = slut;
  }
  
  public double length() {
    double deltaX = start.getX() - slut.getX();
    double deltaY = start.getY() - slut.getY();
    
    return Math.sqrt( deltaX * deltaX + deltaY * deltaY );
  }
}
I length bruger vi to lokale variable, da det øger læsbarheden betydeligt, frem for at have ét samlet udtryk.
Endelig laver vi en testanvendelse, med opbygning af objektsystem og klient:
public class Main {

  public static void main( String[] argv ) {
    // Opbygning af objektsystem
    Linie line = new Linie( new Punkt( 3, 0 ), new Punkt( 0, 4 ) );
    
    // Klient
    System.out.println( line.length() );
  }
}
5.0

 

4 Først laver vi klassen Bil, der skal have en reference til en Motor og en GearKasse.
public class Bil {
  private Motor motor;
  private GearKasse gearKasse;
  
  public Bil( int maxRPM, int stepRPM, int maxGear ) {
    motor = new Motor( maxRPM, stepRPM );
    gearKasse = new GearKasse( maxGear );
  }
  
  public void speedUp() {
    motor.up();
  }
  
  public void speedDown() {
    motor.down();
  }
  
  public void gearUp() {
    gearKasse.up();
  }
  
  public void gearDown() {
    gearKasse.down();
  }
  
  public double getSpeed() {
    return (double) ( motor.getRPM() * gearKasse.getGear() ) / 100;
  }
  
  public String toString() {
    return "[Bil:" + motor + gearKasse + "]";
  }
}
  Dernæst følger klassen GearKasse med en tilstand bestående af det gear som den er i, samt dens maksimale gear.
public class GearKasse {
  private int gear;
  private int maxGear;
  
  public GearKasse( int maxGear ) {
    this.maxGear = maxGear;
    
    gear = 1; // starter altid i 1. gear
  }
  
  public void up() {
    if ( gear + 1 <= maxGear )
      gear++;
  }
  
  public void down() {
    if ( gear - 1 >= 1 )
      gear--;
  }
  
  public int getGear() {
    return gear;
  }
  
  public String toString() {
    return "[Gear=" + gear + "]";
  }
}
  Klassen Motor har tre instansvariable, som holder styr på nuværende RPM, det maksimale RPM og i hvilke skridt RPM ændrer sig.
public class Motor {
  private int rpm;
  private int maxRPM;
  private int stepRPM;
  
  public Motor( int maxRPM, int stepRPM ) {
    this.maxRPM = maxRPM;
    this.stepRPM = stepRPM;

    rpm = 0;
  }
  
  public void up() {
    if ( rpm + stepRPM <= maxRPM )
      rpm += stepRPM;
  }
  
  public void down() {
    if ( rpm - stepRPM >= 0 )
      rpm -= stepRPM;
  }
  
  public int getRPM() {
    return rpm;
  }
  
  public String toString() {
    return "[RPM=" + rpm + "]";
  }
}
Endelig laver vi en testanvendelse, med opbygning af objektsystem og klient:
public class Main {

  public static void main( String[] argv ) {
    // Opbygning af objektsystem
    Bil bil = new Bil( 3000, 250, 4 );
    
    // Klient
    System.out.println( bil.getSpeed() );
    
    for ( int i=0; i<10; i++ ) {
      for ( int j=0; j<10; j++ ) {
        bil.speedUp();
        System.out.println( bil.getSpeed() );
      }
      
      bil.gearUp();
    }
  }
}
0.0
2.5
5.0
7.5
10.0
12.5
15.0
17.5
20.0
22.5
...

Udskriften er afkortet.

 

5
private Tidspunkt først( Tidspunkt t1, Tidspunkt t2 ) {
  if ( t1.compareTo( t2 ) < 0 )
    return t1;
  else
    return t2;
}

private Tidspunkt sidst( Tidspunkt t1, Tidspunkt t2 ) {
  if ( t1.compareTo( t2 ) > 0 )
    return t1;
  else
    return t2;
}

 

6 Begge metoder bygger på en samme idé. Man kalder varighed på de to instanser af Periode som det drejer sig om: Os selv og den anden (givet ved parameteren p).
 
public boolean equals( Periode other ) {
  return varighed().equals( other.varighed() );
}

 
public int compareTo( Periode other ) {
  return varighed().compareTo( other.varighed() );
}

  Bemærk at kaldet af vores egen varighed returnerer en reference til et Tidspunkt og at vi sender et equals-, henholdsvis compareTo-kald via denne reference med det samme - i samme linie!