Kihagyás

4. gyakorlat

A gyakorlat anyaga

Factory Method

  • Cél: interfész definiálása egy objektum létrehozásához, de csak a származtatott osztályok döntik el a tényleges osztályt
  • Alkalmazhatóság:
    • egy osztály nem tudhatja előre melyik osztályból példányosítson
    • egy osztály a származtatottjaitól várja el, hogy meghatározzák a példányosított objektumot

Példa

A zenelejátszónknak playlisteket tudunk adni. Alapvetően sorban játszuk le a zenéket, de buli üzemmódban véletlenszerű lejátszást kell produkálnunk.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayList;
import java.util.List;

public class MusicPlayer {

    private List<String> playlist;

    public void playPlaylist(List<String> playlist) {
        this.createPlaylist(playlist);
        this.play();
    }

    protected void createPlaylist(List<String> playlist) {
        this.playlist = new ArrayList<>(playlist);
    }

    private void play() {
        for (String track : this.playlist) {
            System.out.println("Playing: " + track);
        }
    }

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ShufflePlayer extends MusicPlayer {

    @Override
    protected void createPlaylist(List<String> playlist) {
        List<String> list = new ArrayList<>(playlist);
        Collections.shuffle(list);
        super.createPlaylist(list);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import java.util.Arrays;

public class Client {

    public static void main(String[] args) {
        boolean shuffleIsOn = true;
        MusicPlayer musicPlayer;
        if (shuffleIsOn) {
            musicPlayer = new ShufflePlayer();
        } else {
            musicPlayer = new MusicPlayer();
        }
        musicPlayer.playPlaylist(Arrays.asList("Kozso - Szomoru Szamuraj", "Psy - Gangnam Style", "Slipknot - Duality", "Linkin Park - In the end"));
    }
}

Abstract Factory

  • Cél: kapcsolódó vagy függő objektumcsaládok létrehozása a konkrét osztály megnevezése nélkül
  • Alkalmazhatóság:
    • rendszer független a termékek szerkezetétől, gyártásától
    • több termékcsalád kell hogy legyen
    • termékcsalád termékeit együtt kell használni
    • A különböző családok termékei "nem illenek össze"
    • termékek implementációja rejtett, interfész adott

Példa

  • Egy autós játékot készítünk, melyben a játékos különböző korszakokban versenyezhet bizonyos típusú gépjárművekkel (motor, autó, teherautó).
  • A játék attól függően változtatja a kinézetét a járműnek, hogy épp melyik korszakban vagyunk.

  • Motor

1
2
3
public interface IBike {
    void ride();
}
1
2
3
4
5
6
7
public class Kawasaki implements IBike {

    @Override
    public void ride() {
        System.out.println("Riding a Kawasaki bike.");
    }
}
1
2
3
4
5
6
7
public class Simson implements IBike {

    @Override
    public void ride() {
        System.out.println("Riding a Simson bike.");
    }
}
  • Autó
1
2
3
public interface ICar {
    void drive();
}
1
2
3
4
5
6
7
public class Ford implements ICar {

    @Override
    public void drive() {
        System.out.println("Driving a Ford car.");
    }
}
1
2
3
4
5
6
7
public class Trabant implements ICar {

    @Override
    public void drive() {
        System.out.println("Driving a Trabant.");
    }
}
  • Teherautó
1
2
3
public interface ITruck {
    void carry();
}
1
2
3
4
5
6
7
public class Ifa implements ITruck {

    @Override
    public void carry() {
        System.out.println("Carrying stuff with an IFA.");
    }
}
1
2
3
4
5
6
7
public class Volvo implements ITruck {

    @Override
    public void carry() {
        System.out.println("Carrying stuff with a Volvo truck.");
    }
}
  • Factory-k
1
2
3
4
5
6
7
8
public interface VehicleFactory {

    IBike createBike();

    ICar createCar();

    ITruck createTruck();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class OldVehicleFactory implements VehicleFactory {

    @Override
    public IBike createBike() {
        return new Simson();
    }

    @Override
    public ICar createCar() {
        return new Trabant();
    }

    @Override
    public ITruck createTruck() {
        return new Ifa();
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class ModernVehicleFactory implements VehicleFactory {

    @Override
    public IBike createBike() {
        return new Kawasaki();
    }

    @Override
    public ICar createCar() {
        return new Ford();
    }

    @Override
    public ITruck createTruck() {
        return new Volvo();
    }
}
  • Kliens
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class Client {

    public static void main(String[] args) {
        VehicleFactory vf;
        boolean nostalgia = true;
        if (nostalgia) {
            vf = new OldVehicleFactory();
        } else {
            vf = new ModernVehicleFactory();
        }

        vf.createBike().ride();
        vf.createCar().drive();
        vf.createTruck().carry();
    }
}

Iterator

  • Cél: tároló-objektum elemeinek sorozatos elérése a reprezentációtól függetlenül
  • Alkalmazhatóság:
    • egy tároló objektum tartalmát el akarjuk érni függetlenül a belső reprezentációtól
    • egyidejűleg többszörös bejárásra is szükség van
    • egységes interfészre van szükség különböző tároló szerkezetekhez

Példa

Van két típusú listánk - Feladatok listája (TodoList) - ArrayListben tárol - Feladatok gyűjteményének listája (ToDoListCollection) - HashMapben tárol - A két listát egységesen akarjuk bejárni - Az egységes bejárással kiíratjuk a feladatokat (ListPrinter)

1
2
3
4
5
6
7
8
9
public class Channel {
    public double freq;
    public String name;

    public Channel(String name, double freq) {
        this.name = name;
        this.freq = freq;
    }
}
1
2
public abstract class Tv implements Iterable<Channel> {
}
 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
public class OldTv extends Tv {

    private Channel[] channels;

    public OldTv(Channel[] channels) {
        this.channels = new Channel[10];
        System.arraycopy(channels, 0, this.channels, 0, 10);
    }

    @Override
    public Iterator<Channel> iterator() {
        return new OldTvIterator();
    }

    private class OldTvIterator implements Iterator<Channel> {
        int current = 0;

        @Override
        public boolean hasNext() {
            return current < 10;
        }

        @Override
        public Channel next() {
            if (this.hasNext()) {
                return channels[current++];
            }
            return null;
        }

    }
}
 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
public class NewTv extends Tv {

    private List<Channel> channels;

    public NewTv(Channel[] channels) {
        this.channels = new ArrayList<>();
        Collections.addAll(this.channels, channels);
    }

    @Override
    public Iterator<Channel> iterator() {
        return new NewTvIterator();
    }

    private class NewTvIterator implements Iterator<Channel> {
        int current = 0;

        @Override
        public boolean hasNext() {
            return current < channels.size();
        }

        @Override
        public Channel next() {
            if (this.hasNext()) {
                return channels.get(current++);
            }
            return null;
        }

    }
}
 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
package hu.u_szeged.inf.ovrt.iterator;

public class Client {
    public static void main(String[] args) {
        Channel[] channels = {
                new Channel("m1", 120.3),
                new Channel("m2", 121.4), new Channel("m3", 134.73),
                new Channel("m4", 150.1), new Channel("ker1", 220.3),
                new Channel("ker2", 221.4), new Channel("ker3", 234.73),
                new Channel("ker4", 250.1), new Channel("sport1", 320.3),
                new Channel("sport2", 321.4), new Channel("sport3", 334.73),
                new Channel("sport4", 350.1), new Channel("zene1", 420.3),
                new Channel("zene2", 421.4), new Channel("zene3", 434.73),
                new Channel("zene4", 450.1),
        };

        boolean oldTv = false;
        Tv television;
        if (oldTv) {
            television = new OldTv(channels);
        } else {
            television = new NewTv(channels);
        }

        for (Channel c : television) {
            System.out.println("Egy csatorna a tv-n: " + c.name);
        }

    }
}

Feladatok

  1. Készítsünk egy kávézós alkalmazást. Legyen benne:
    • absztrakt KávéHáz osztályunk:
    • két kávéház: egyszerű és hipster
    • két terméket készítenek: süti, kávé
    • minden terméknek legyen neve, ára
    • A hipster termékek ára a nevüktől függjön
      • A mucsaröcsögei feketelevelű tuskókávé ára legyen több, mint az eszpresszóé

Utolsó frissítés: 2021-10-14 12:46:56