Programutvecklingsteknik 15 jan 2003

Övning 1 med lösning

  1. I byrån finns en strumplåda och en kalsonglåda. Objektmodellera och ge exempel på användning!


  2. Skapa en komponent Pnrfält som har en rubrik och ett tomt fält och som vid returtryckning kollar att personnumret är rätt och fyller i eventuellt bortglömt bindestreck.


  3. Mejerikylen i butiken behöver ett program för att ta in lagom mycket mjölk så att den helst inte hinner bli för gammal osv. Objektmodellera! Skissa hur en simulering med programmet skulle gå till!


  4. Om ett par veckor går EM i konståkning i Budapest. Gör en objektmodell för paråkningen! Det finns nio domare, varje par åker först ett kort program och får poäng, dom bästa sexton får sedan åka sitt långa program och får nya poäng som adderas till dom tidigare. Vilka hopp och andra moment som ska göras i varje program måste paren anmäla i förväg.


LÖSNINGAR

Man ska alltid rita objekten enligt enklaste UML-standard,
dvs "har"-relation är ett vanligt streck mellan rutorna och
"är" relation är en pilen från subklass till superklass.
Vid har-relation sätter man en etta intill ägarklassen och
1,2,...,* intill ägdaklassen. 

    ____          ____        _____
1  |Byrå|1      2|Låda|1    *|Plagg|
   |____|--------|____|------|_____|
                              ^   ^
                              |   |
                        Strumpa   Kalsong

   Eftersom saker alltid hamnar fel måste man ha superklassen
   Plagg som generaliserar Strumpa och Kalsong.

   Kopplingen Byrå-Låda bör vara en vektor men Låda-Plagg en
   abstrakt kö. Lämpliga metoder i Låda är put och get, i Byrå
   put, get, open och close.

   I huvudprogrammet finns Byrå byrån = new Byrå(2);//tvålådors
   och konstruktorn gör förstås new Låda() lagom många gånger.
   Exempel på kod:
         byrån.open(1); //öpnna översta lådan
         byrån.put(new Strumpa("vit tub"));
         byrån.close();
         byrån.open(2);
         byrån.put(new Kalsong("skär spets"));

   Inbjud till diskussion om följande problem. Man vill ha tag i
   ett par matchande strumpor. Hur gör man? Förslagen kommer att
   vara ungefär "öppna strumplådan, ta ett plagg, om det inte är
   en strumpa stoppas den tillbaka, håll på tills du hittat en
   strumpa, behåll den, fortsätt på samma sätt tills du hittat
   den matchande strumpan". Felet med det förslaget är att det
   kan gå runt i oändlig slinga om den andra strumpan råkat
   hamna i kalsonglådan. Be om lösningsförslag till detta.
   En möjlighet är att den abstrakta kön har ett anrop
   numberOfElements() så att man kan köra en for-slinga just
   så många varv. En annan är att man lägger ner ett markörplagg
   för att veta när man gått runt ett varv.

   Om man väljer en abstrakt stack i stället för en abstrakt kö
   så får man en annan metod att plocka i lådan. Då fungerar ens
   egen famn som en tillfällig hjälpstack. 

2  Komponenterna Label och TextField slås ihop i en behållare Panel.

                            ____
                           |Panel|
                           |_____|
                              ^
                            __|_____        _____
     ___________           |Pnrfält |------|Label|
    |ActionEvent| - - - - >|        |      |_____|
    |returtryck |          |        |       _________
    |___________|          |________|------|TextField|- - -
        ^                                  |_________|     |
        | _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _


  Streckade pilen betyder att Pnrfält lyssnar efter händelsen,
  den ska alltså själv vara en ActionListener.

   import java.awt.*;
   import java.awt.event.*;
   public class Pnrfält extends Panel implements ActionListener   {
       Label rubrik = new Label("Pnr:")                           ;
       TextField pnr = new TextField(15)                          ;
       public Pnrfält()                                           {
           add(rubrik)                                            ;
           pnr.addActionListener(this)                            ;
           add(pnr)                                               ;}
       public void actionPerformed(ActionEvent e)                 {
   	   String p=pnr.getText()                                 ;
           if(p.charAt(6)=='-') p=p.substring(0,6)+p.substring(7) ;
           int summa=0                                            ;
           for(int i=0;i<10;i++)                                  {
   	     int x=p.charAt(i)-48                                 ;
   	     if(i%2==0) x=2*x                                     ;
      	     summa=summa+x/10+x%10                                ;}
           if(summa%10!=0) pnr.setText(p+"FEL")                   ;
           else pnr.setText(p.substring(0,6)+"-"+p.substring(6))  ;}}
 

3   ___ 1      * ____
   |Kyl|--------|Vara|     Så här ser första försöket ut. Det visar
   |___|        |____|     sej dock att klassen Queue också behövs.

   import java.util.*  ;   //Där finns Date.
   public class Vara   {   //Några metoder kanske inte behövs i
     String namn       ;   //klassen men om man är fanatiker vill
     double volym      ;   //ha fälten privata och ha konstruktor
     Date   bästföre   ;}  //och åtkomstmetoder.
                           
Vi kan använda en abstrakt kö att lägga varorna i. Eftersom Queue.get()
returnerar ett Object får vi typa om det till Vara.
 
   import java.util.*;
   public class Kyl                                                     {
     private double totalvolym                                          ;
     private double varuvolym                                           ;
     private Queue varor = new Queue()                                  ;
     public void put(Vara varan) throws Exception                       {
       if(varan.volym+varuvolym>totalvolym) throw new Exception("Fullt");
       varuvolym+=varan.volym                                           ;
       varukö.put(varan)                                                ;}
     public Vara get() throws Exception                                 {
       if(varukö.isEmpty()) throw new Exception("Tomt")                 ;
       Vara varan=(Vara)varukö.get()                                    ;
       varuvolym-=varan.volym                                           ;
       return varan                                                     ;}}

För att plocka en liter minimjölk som inte har gått ut kan man göra
  for(int i=0;i<1000;i++)             {//för att undvika oändlig loop
   Vara varan=kylen.get()             ;
   if(varan.namn.equals("minimjölk")
     &&varan.datum.after(today)) break;
   kylen.put(varan)                   ;}
Diskutera om det finns andra sätt.

UML-diagrammet för en kö ser ut så här. Hur ska det fogas in mellan Kyl
och Vara?
                       ____
                      |    |
        ______      __V_   |     ______
       |Queue |--->|Node|---    |Object|
       |______|--->|____|------>|______|


4        _____ 2   1 ___ *     1 _______ 1     9 ______
        |Åkare|-----|Par|-------|Tävling|-------|Domare|       
        |_____|     |___|       |_______|       |______|
                   ___|2__       ___|2__      
                  |Program|     |Tabell |     
                  |_______|     |_______|     
 Tabellobjekt ger åkordning och poäng för korta eller långa programmet
 och programobjekt visar vilka hopp som ska ingå.
 En domare ger poäng till ett par med metodanrop av typen 
 korttabell.put(par,domare,poäng). En sorterad lista med aktuellt läge
 kanske visas på skärmen av långtabell.show().
   

^ Upp till kurssidan.


Sidansvarig: <henrik@nada.kth.se>
Senast ändrad 21 januari 2004
Tekniskt stöd: <webmaster@nada.kth.se>