Praktikum 7. Mustrid, XML.



ÜLESANDED KLASSIS

Võtta aluseks kalkulaatori-rakenduse skelett: http://courses.cs.ut.ee/tvt/lab7/lab7-calculator-skeleton.zip

Refaktoreerime olemasolevat kalkulaatorit nii, et uus disain võimaldaks ilma Caclulator klassi muutmata uusi tehteid juurde lisada. Vaatame, milliseid mustreid saame seejuures kasutada.

1. Toetatavate operatsioonide abstrahheerimine.

  • Kalkulaatori poolt toetatavate operatsioonide abstrahheerimine strategy patterni abil.
  • Eesmärk: klass Calculator peaks olema laiendatav selliselt, et selle kasutajad saaksid lisada uusi operatsioone (tehteid) ilma klassi ennast muutmata. (Taolised nõudmised on väga tüüpilised erinevatele frameworkide disainimisel. Seejuures on oluline, et kasutajad saaksid selle erinevaid osasid kerge vaevaga laiendada, aga ei peaks seejuures muutma frameworki enda klasse).
  • Teostus:
    1. Lahendada ülesanne kasutades strategy patternit. Luua tehete jaoks interface BinaryOperation ja seda realiseerivad klassid AdditionOperation liitmise ja SubtractionOperation lahutamise jaoks.
    2. Lisada klassi Calculator meetod performOperation, mis võtab argumendiks objekte tüüpi BinaryOperation ja teostab vastavaid tehteid.
    3. Muuta klassi Calculator meetodeid add ja subtract, et kasutataks liitmist ja lahutamist realiseerivaid operatsiooniklasse ja meetodit performOperation.
    4. Lisada ka analoogne interface UnaryOperation unaarsete tehete jaoks (näiteks ruutu tõstmine, kuupi tõstmine, faktori leidmine, jne).
    5. Kontrollida, et olemasolevad automaattestid endiselt läbiksid. Lisada testidesse uus test-meetod korrutamise testimiseks ja kontrollida et see läbiks:
    @Test
    public void testMultiply() {
        BinaryOperation multiply = new BinaryOperation() {
            public Integer performOperation(Integer a, Integer b) {
                return a*b;
            }
        };

        // 7 * 3 = 21?
        calculator
            .setDisplayValueTo(7)
            .performOperation(multiply, 3);
        assertEquals(calculator.getDisplayValue(), new Integer(21));
    }

2. Operatsioonide loomise viimine factory'sse

  • Eesmärk: interface'i BinaryOperation realiseerivate klasside isendite loomine viikse klassi OperationFactory.
  • Teostus:
    1. Luua klass OperationFactory, millel on staatilised meetodid BinaryOperation isendite loomiseks:
      • public static BinaryOperation createAdditionOperation()
      • public static BinaryOperation createSubtractionOperation()
      • public static BinaryOperation createMultiplicationOperation()
      • public static UnaryOperation createSquareOperation()
    2. Muuta klassi Calculator ja ka teste nii, et igal pool BinaryOperation isendite loomiseks kasutataks OperationFactoryt.
    3. Peale seda võib kaotada ka nüüdseks üleliigsed klassid AdditionOperation ja SubtractionOperation.

3. Valemite kirjeldamine puuna

  • Eesmärk: Kalkulaator panna ainult viimase väärtuse asemel meelde jätma kogu järjestikkust arvutuskäiku valemina. Valemid esitada composite pattern abil puu-struktuurina.
  • Teostus:
    1. Luua interface AbstractValue ja seda laiendavad klassid:
      • SimpleValue - sisaldab ainult ühte Integer välja
      • UnaryOperationValue - sisaldab mingit UnaryOperation tehet ja tehte argumenti tüübina IValue.
      • BinaryOperationValue - sisaldab mingit BinaryOperation tehet ja kahte tehte argumenti tüüpidena IValue
  • Näide:
    • Näiteks valem (7^2 + 1) * 2 näeks puu kujul välja järgmine. Kui kujutada ette taskukalkulaatorit, siis sellise tulemuseni jõudmiseks tuleks järjest vajutada kalkulaatori nuppe "7", "^2", "+", "1", "*", "2". Vaata ka all järgnevat testi.
  1. Lisada testide hulka järgmine test. Lõpuks peab see test läbima:
    @Test
    public void testEquation() {

        // (7^2 + 1) * 2  == 100? 
    	calculator
    		.setDisplayValueTo(7)
    		.performOperation(OperationFactory.createSquareOperation())
    		.performOperation(OperationFactory.createAdditionOperation(), 1)
    		.performOperation(OperationFactory.createMultiplicationOperation(), 2);

        assertEquals(calculator.getDisplayValue(), new Integer(100));
    }



ÜLESANDED KODUS

Ülesanne 1. Mustrite leidmine.

Leida etteantud koodist järgnevad disainimustrid ja joonista koodist lähtuvalt nende klassidiagrammid:

Mustrite osade märkimiseks koodis kasuta annotatsioone (javadoc). Vaata lisaks ka slaide annotatsioonide seotust mustrite erinevate osadega.

Soovituslik tööde järjekord:

  • Joonista klassidiagrammid koodi kohta( java klasside ja UML diagrammide seos )
  • Kasutades klassidiagramme leia mustrid (üks ja sama klass võib olla mitme mustri osa)
  • Joonista klassidiagrammid iga mustri kohta - jäta sinna ainult mustriga seotud osad

NB! Annotatsioonidega kood ja klassidiagrammid mustrite kohta tuleb esitada koos kodutööga!



Ülesanne 2. Kassasüsteemi täiendamine: maksmisega hilinemise viivised.

Süsteemile on lisandunud veel üks nõue: klient peab soovi korral saama ostu eest tasuda hiljem. Kliendile lisatakse maksmise kuupäev. Kui klient järgmisel korral ostma tuleb, kuvab süsteem võla, kui see on olemas ja enne uut ostu ei saa sooritada kui vana võlg on makstud. Iga üleläinud päeva eest on viivis x% algsest summast mis liidetakse esialgsele summale.

Viiviste suuruseid peab olema võimalik ilma programmeerija abita võimalik paindlikult muuta. Selleks lisatakse kassasüsteemile XML konfiguratsioonifail, mida süsteemi käivitamisel iga kord uuesti loetakse. Fail sisaldab lihtsaid reegleid mille järgi mingi kliendi viivisemäär mingil kindlal hetkel kindlaks määratakse. XML-faili formaat koos täiendavate selgitustega on ette antud ja selle spetsifitseerib näidisfail penalty_conf.xml. Konfiguratsioonifaili abiga on võimalik:

  • Anda teatud klientidele personaalne viivisemäär (või teha seda ainult teatud kindlaks perioodiks).
  • Anda kõikidele klientidele mingiks kindlaks perioodiks tavalisest erinev viivisemäär.
  • Muuta kõikide klientide üldist viivisemäära.

Soovi korral on võimalus XML-faili reeglite järgi viivisemäärade valimine ka välja lülitada. Selleks kasutatakse ära abstract factory mustrit. Nimelt sisaldab kassasüsteem kahte erinevat StrategyFactory implementatsiooni:

  • ee.ut.math.tvt.salessystem.penalty.identity.IdentityStrategyFactory - "tühi" viiviste arvutamise strateegia, mis tegelikult viiviseid ei lisa (viivis on alati 0).
  • ee.ut.math.tvt.salessystem.penalty.standard.InterpreterStrategyFactory - viiviste arvutamise strateegia, mis arvutab viiviseid vastavalt konfiguratsioonifailist loetud viivisemäära reeglitele

Otsustamaks, kumba StrategyFactoryt kasutada, antakse kassasüsteemile käivitamisel ette spetsiaalne JVM parameeter -Dpenalty.strategy.factory, mille väärtuseks antakse soovitava StrategyFactory implementatsiooni täispikk klassinimi.

Kaks erinevat viivise arvutamise strateegiat/algoritmi (null-viivised ja XML konfiguratsioonist tulenevad viivised) on realiseeritud strategy pattern abiga (vt interfacei ee.ut.math.tvt.salessystem.penalty.Strategy) :

  • Algoritmi sisenditeks on klient, maksekuupäev ning ost.
  • Algoritmi väljundiks on allahindlusprotsent (täpsemalt objekt ee.ut.math.tvt.salessystem.penalty.Penalty).

Teie ülesandeks on võtta aluseks penalty.zip sisu (vt allpool) ning ülalkirjeldatud täiendused kassasüsteemis realiseerida. Selleks on vaja:

  1. Realiseerida XML-faili parser konfiguratsioonifaili parsimiseks (klassi ee.ut.math.tvt.salessystem.penalty.standard.ConfigurationReader) ning lisda kassasüsteemile algne konfiguratsioonifail, mida klient saaks edaspidi muuta (võib kasutada näidist).
  2. Lisada ehitusskripti JVM argumendi penalty.strategy.factory etteandmine kassasüsteemi käivitamisel.
  3. Realiseerida võlgu jäämine ja võla/viivise tasumine kasutajaliideses.
  4. Realiseerida viiviste algoritm, mis vastab viivise puudumisele (ee.ut.math.tvt.salessystem.penalty.identity.IdentityStrategy).
  5. Realiseerida viiviste algoritm, mis arvutab viivised vastavalt XML-failis sisalduvatele reeglitele (klassi ee.ut.math.tvt.salessystem.penalty.standard.InterpreterStrategy).

Alustamiseks teha olemasolevale rakendusele järgmised täiendused:

  • Laadida alla penalty.zip ja pakkida see lahti kassasüsteemi juurkausta.
  • Käivitada DBManageris järgnevad sql-id:
    • alter table client add due_date date;
    • alter table client add due_sale integer;
  • Lisada Client klassile järgnevad väljad koos vastavate getter ja setter meetoditega:
    •  @Column(name="due_date")
       private Date dueDate; 
    •  @ManyToOne
       @JoinColumn(name = "due_sale", unique=true)
       private Sale dueSale;

Abiks viivise arvutamise komponendi disaini mõistmisel:



VIITED



Sidebar
Page edit