Kihagyás

7. gyakorlat

A gyakorlat anyaga

State

  • Cél: objektum viselkedésének megváltoztatása belső állapotváltozás hatására (kívülről úgy tűnik, mintha az osztályát változtatná meg)
  • Alkalmazhatóság:
    • objektum viselkedése állapotának függvénye, és az futás közben változhat
    • operációkban nagy elágazások vannak, többen ugyanazon szerkezettel, pl. valami konstanstól függővé téve

Példa

  • Egy RPG kalandjátékban a karakterünk attól függően, hogy milyen műveletet végzünk vele több állapotban is lehet.
  • Az egyes műveletek végrehajtásának az eredménye függ az adott állapottól is.
Stance.java
1
2
3
4
5
6
7
public interface Stance {

    int handleDefense(int defensePower);

    int handleAttack(int attackPower);

}
AngryStance.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class AngryStance implements Stance {

    private static final double criticalStrikeChance = 0.3;

    @Override
    public int handleDefense(int defensePower) {
        return 0;
    }

    @Override
    public int handleAttack(int attackPower) {
        return Math.random() > criticalStrikeChance ? attackPower : attackPower * 2;
    }

}
DefensiveStance.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class DefensiveStance implements Stance {

    @Override
    public int handleDefense(int defensePower) {
        return defensePower * 2;
    }

    @Override
    public int handleAttack(int attackPower) {
        return attackPower / 2;
    }

}
NormalStance.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class NormalStance implements Stance {

    @Override
    public int handleDefense(int defensePower) {
        return defensePower / 2;
    }

    @Override
    public int handleAttack(int attackPower) {
        return attackPower;
    }

}
Character.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public class Character {

    private String name;
    private int lifePoint;
    private int attackPower;
    private int defensePower;
    private Stance currentStance;

    public Character(String name, int lifePoint, int attackPower, int defensePower) {
        super();
        this.name = name;
        this.lifePoint = lifePoint;
        this.attackPower = attackPower;
        this.defensePower = defensePower;
        this.currentStance = new NormalStance();
    }

    public void changeStance(Stance stance) {
        this.currentStance = stance;
    }

    public void attack(Character enemy) {
        int myAttack = this.currentStance.handleAttack(this.attackPower);
        int enemyDefense = enemy.currentStance.handleDefense(enemy.defensePower);
        int damageToEnemy = Math.max(myAttack - enemyDefense, 0);
        System.out.println(String.format("%s attacked %s with %d. %s lost %d life points, %d remains.", this, enemy,
                myAttack, enemy, damageToEnemy, enemy.lifePoint - damageToEnemy));
        enemy.lifePoint -= damageToEnemy;
    }

    public boolean isAlive() {
        return this.lifePoint > 0;
    }

    @Override
    public String toString() {
        return this.name;
    }

}
Client.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Client {

    public static void main(String[] args) {
        Character orc = new Character("Azog", 100, 20, 5);
        orc.changeStance(new AngryStance());

        Character dwarf = new Character("Thorin", 100, 15, 10);
        dwarf.changeStance(new DefensiveStance());

        boolean turn = true;
        while (orc.isAlive() && dwarf.isAlive()) {
            if (turn) {
                orc.attack(dwarf);
            } else {
                dwarf.attack(orc);
            }
            turn = !turn;
        }
        System.out.println("The winner is: " + (orc.isAlive() ? orc : dwarf));
    }

}

Strategy

  • Cél: algoritmus-család meghatározása, melyben az egyes algoritmusokat egységbe zárjuk, és egymással felcserélhetővé tesszük.
  • Alkalmazhatóság:
    • hasonló osztályok csak viselkedésben különböznek, így a különbözően viselkedő objektumokhoz különböző viselkedést rendelhetünk
    • egy algoritmus több változata: idő/tár optimalizálás,

Példa

  • Egy alkalmazásban beállítástól függően gombnyomásra menthetünk json-be, vagy xml-be.
  • A beállításokat módosíthatjuk bármikor, a gomb megnyomására pedig a beállított módon történik meg a mentés
Writer.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

interface Strategy{
    public void write(Map<String, String> map);
}

class JsonPrinterStrategy implements Strategy{

    @Override
    public void write(Map<String, String> map) {
        System.out.println("{");
        map.forEach( (k, v) -> {
            System.out.println(String.format("    \"%s\": \"%s\",", k, v));
        });
        System.out.println("}");
    }

}

class XmlPrinterStrategy implements Strategy{

    @Override
    public void write(Map<String, String> map) {
        System.out.println("<root>");
        map.forEach( (k, v) -> {
            System.out.println(String.format("    <%s>%s</%s>", k, v, k));
        });
        System.out.println("</root>");

    }

}


public class Writer {
    private static final Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        Map<String, String> strMap = new HashMap<>();
        strMap.put("name", "John Johny John");
        strMap.put("age", String.valueOf(30));
        strMap.put("fav_music", "Queen");

        Strategy s;
        System.out.println("Which strategy to use? (json/xml)");
        String strategy = sc.nextLine();
        if(strategy.equals("json")){
            s = new JsonPrinterStrategy();
        } else {
            s = new XmlPrinterStrategy();
        }
        s.write(strMap);
    }
}

Interpreter

  • Cél: egy nyelv nyelvtanának reprezentálása a hozzá tartozó interpreterrel (szintaxis fa épül, majd a nyelv szavai ezen lesznek elemezve)
  • Alkalmazhatóság:
    • nyelv megadható, melynek szintaxisfáján történhet az elemzés
    • nagyobb feladatokhoz jobbak az elemző-generátorok (osztályhierarchia nagy lehet)
      • Pl.: ANTLR

Példa

  • Van egy személyek elérhetőségét (Contact) tároló kollekciónk (ContactList).
  • Interpreter segítségével definiálunk egy kifejezést, amit arra használhatunk, hogy a kollekcióban az adott kritériumoknak megfelelő Contact-okra keresve visszakapjuk a megfelelő Contact-ok egy halmazát
MainInterpreter.java
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import java.util.ArrayList;
import java.util.Iterator;

class Context {

    private String input;
    private int output;

    public Context(String input) {
        this.input = input;
    }

    public String getInput() {
        return input;
    }

    public void setInput(String input) {
        this.input = input;
    }

    public int getOutput() {
        return output;
    }

    public void setOutput(int output) {
        this.output = output;
    }

}

abstract class Expression {

    public void interpret(Context context) {
        if (context.getInput().length() == 0)
            return;

        if (context.getInput().startsWith(nine())) {
            context.setOutput(context.getOutput() + (9 * multiplier()));
            context.setInput(context.getInput().substring(2));
        } else if (context.getInput().startsWith(four())) {
            context.setOutput(context.getOutput() + (4 * multiplier()));
            context.setInput(context.getInput().substring(2));
        } else if (context.getInput().startsWith(five())) {
            context.setOutput(context.getOutput() + (5 * multiplier()));
            context.setInput(context.getInput().substring(1));
        }

        while (context.getInput().startsWith(one())) {
            context.setOutput(context.getOutput() + (1 * multiplier()));
            context.setInput(context.getInput().substring(1));
        }
    }

    public abstract String one();

    public abstract String four();

    public abstract String five();

    public abstract String nine();

    public abstract int multiplier();

}

class ThousandExpression extends Expression {

    public String one() {
        return "M";
    }

    public String four() {
        return " ";
    }

    public String five() {
        return " ";
    }

    public String nine() {
        return " ";
    }

    public int multiplier() {
        return 1000;
    }
}

class HundredExpression extends Expression {
    public String one() {
        return "C";
    }

    public String four() {
        return "CD";
    }

    public String five() {
        return "D";
    }

    public String nine() {
        return "CM";
    }

    public int multiplier() {
        return 100;
    }
}

class TenExpression extends Expression {
    public String one() {
        return "X";
    }

    public String four() {
        return "XL";
    }

    public String five() {
        return "L";
    }

    public String nine() {
        return "XC";
    }

    public int multiplier() {
        return 10;
    }
}

class OneExpression extends Expression {
    public String one() {
        return "I";
    }

    public String four() {
        return "IV";
    }

    public String five() {
        return "V";
    }

    public String nine() {
        return "IX";
    }

    public int multiplier() {
        return 1;
    }
}

public class MainInterpreter {

    /**
     * @param args
     */
    public static void main(String[] args) {

        String roman = "MCMXXVIII";
        Context context = new Context(roman);

        // Build the 'parse tree'
        ArrayList<Expression> tree = new ArrayList<>();
        tree.add(new ThousandExpression());
        tree.add(new HundredExpression());
        tree.add(new TenExpression());
        tree.add(new OneExpression());

        // Interpret
        for (Expression exp : tree) {
            exp.interpret(context);
        }

        System.out.println(roman + " = " + Integer.toString(context.getOutput()));
    }
}

Visitor

Feladatok

  1. Az alábbiakban megtalálható a CeilingFanExercise.java fájl. Tanulmányozzuk, alakítsuk át úgy, hogy legyen benne tervezési minta.
    • Melyik mintát alkalmazhatjuk?
    • Alakítsuk át, próbáljuk ki.
    • Adjunk hozzá egy új fokozatot is!
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import java.util.Scanner;

class CeilingFanPullChain {
    private int currentState;

    public CeilingFanPullChain() {
        currentState = 0;
    }

    public void pull() {
        if (currentState == 0) {
            currentState = 1;
            System.out.println("low speed");
        } else if (currentState == 1) {
            currentState = 2;
            System.out.println("medium speed");
        } else if (currentState == 2) {
            currentState = 3;
            System.out.println("high speed");
        } else if (currentState == 3) {
            currentState = 4;
            System.out.println("ultra high");
        } else {
            currentState = 0;
            System.out.println("turning off");
        }
    }
}

public class CeilingFanExercise {
    private static final Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        CeilingFanPullChain chain = new CeilingFanPullChain();
        while (true) {
            System.out.print("Press ENTER to pull the ceiling fan!");
            sc.nextLine();
            chain.pull();
        }
    }

}
  1. Az alábbiakban megtalálható a MusicLibraryExercise.java fájl. Tanulmányozzuk, alakítsuk át úgy, hogy legyen benne tervezési minta. Jelenlegi gondok?!
    • Minden műfajt egyesével szeretném kikérni (rap, classic, stb). Mindenre kéne egy getter? Egybemosódik az adatszerkezet és az algoritmusok.
    • Mi van akkor, ha szeretnék rap és rock zenéket keresni? Egyesével, majd a halmazokat egyesítem? Írjak rá külön egy metódust? Sehogy sem túl jó jelenleg…
    • Melyik minta lehet?
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

interface Visitor<T> {
    void visit(Set<T> items);
}

class Music implements Comparable<Music>{
    public String artist;
    public String name;
    public String genre;
    boolean isCompactDisc;
    boolean isMusicDvd;

    public Music(String artist, String name, String genre) {
        this.artist = artist;
        this.name = name;
        this.genre = genre;
        this.isCompactDisc = false;
        this.isMusicDvd = false;
    }

    public Music(String name, String artist, String genre, boolean isCompactDisc, boolean isMusicDvd) {
        this.artist = artist;
        this.name = name;
        this.genre = genre;
        this.isCompactDisc = isCompactDisc;
        this.isMusicDvd = isMusicDvd;

    }


    @Override
    public String toString() {
        return String
                .format("Music [artist=%s, name=%s, genre=%s, isCompactDisc=%s, isMusicDvd=%s]", artist, name, genre, isCompactDisc, isMusicDvd);
    }

    @Override
    public int compareTo(Music o) {
        String tmp1 = this.artist + " " + this.name;
        String tmp2 = o.artist + " " + o.name;
        return tmp1.compareTo(tmp2);
    }

}

class MyMusicLibrary {
    private Set<Music> musicCollection = new TreeSet<Music>();

    public void add(Music m) {
        musicCollection.add(m);
    }

    public Set<Music> getRockMusic(){
        return this.musicCollection.stream().filter(m -> "rock".equalsIgnoreCase(m.genre)).collect(Collectors.toSet());
    }

    public Set<Music> getPopMusic(){
        return this.musicCollection.stream().filter(m -> "pop".equalsIgnoreCase(m.genre)).collect(Collectors.toSet());
    }

}

public class MusicLibraryExercise {
    public static void main(String[] args) {
        MyMusicLibrary library = new MyMusicLibrary();
        library.add(new Music("Thunderstruck", "AC/DC", "rock", false, false));
        library.add(new Music("Who Made Who", "AC/DC", "rock", false, false));
        library.add(new Music("Whole Lotta Rosie", "AC/DC", "rock", false, false));
        library.add(new Music("Growin Up", "Bruce Springsteen", "pop", false, false));
        library.add(new Music("Crossroads", "Cream", "pop", false, false));
        library.add(new Music("Jean Genie", "David Bowie", "rap", false, false));
        library.add(new Music("Boulevard Of Broken Dreams", "Green Day", "rap", false, false));
        library.add(new Music("Little Queen", "Heart", "folk", false, false));
        library.add(new Music("Nothing Is Easy", "Jethro Tull", "folk", false, false));
        library.add(new Music("All Along the Watchtower", "Jimi Hendrix", "indie", false, false));
        library.add(new Music("Wheel in the Sky", "Journey", "rock", false, false));
        library.add(new Music("Black Dog", "Led Zeppelin", "alternative", false, false));
        library.add(new Music("I'm Down", "The Beatles", "classic", false, false));
        library.add(new Music("No woman no cry", "Bob Marley", "raggae", false, false));
        library.add(new Music("Bridge Over Troubled Water", "Simon And Garfunkel", "punk", false, false));

        System.out.println(library.getRockMusic());
    }
}

Utolsó frissítés: 2021-11-17 11:01:33