Kihagyás

4. gyakorlat

A gyakorlat anyaga

Bevezető

  • A Könyv: Design Patterns: Elements of Reusable object-Oriantated Software
  • Minta leírások és katalógus
  • Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides
    • "Gang of Four" (GOF-minták)
    • Gamma-minták
  • Minden tervezési minta leír egy gyakran előforduló problémát és megadja a hozzá tartozó megoldás lényegét.

  • A minták használatának előnyei:

    • Jobb szoftver dizájn
    • Javuló csapat kommunikáció
    • Közös koncepciók alakulnak ki
    • Hatékonyabb probléma megoldás
  • Példák a Java beépített függvénykönyvtárában: https://stackoverflow.com/a/2707195
  • A könyvben a mintákat nem UML-lel, hanem OMT notation segítségével írják le (ami hasonlít az UML-hez, de van néhány apróbb különbség)

Tervezési minták felépítése

  • Minta neve
    • Kommunikáció, közös nyelv
    • Absztrakt szinten való tervezést tesz lehetővé
  • Probléma leírása
    • Hol lehet alkalmazni. Kontextust írja le.
    • Megadja mi a probléma a mostani módszerrel.
  • Problémára nyújtott megoldás
    • Megadja a megoldás sablonját.
    • Leírja a megoldásban szereplő elemek szerepét.
  • Következmény
    • Kompromisszumok, alternatívák, költségek és nyereségek

A könyvben a minták csoportosítva vannak, katalógusba rendezve.

Singleton

 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
public class Singleton {

  /** holds the single instance for the singleton class */
  private static final Singleton INSTANCE = new Singleton();

  /** private constructor -> no other instance can be created */
  private Singleton() {
    System.out.println("> create instance (!)");
  }

  /**
   * Access method to get the singleton instance.
   * 
   * @return the singleton instance
   */
  public static Singleton getInstance() {
    return INSTANCE;
  }

  public void helloSingleton() {
    System.out.println("Hello! I'm a singleton.");
  }

  // test it
  public static void main(String[] args) {
    System.out.println("> program start");
    Singleton.getInstance().helloSingleton();
    System.out.println("> program finish");
  }
  // Output:
  // > create instance (!)
  // > program start
  // Hello! I'm a singleton.
  // > program finish
}
  • A lusta megoldás
 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
/**
 * Singleton with lazy instantiation.
 * 
 * The singleton instance is created when the getInstance()
 * method is called for the first time.
 */
public class SingletonLazy {

  private static SingletonLazy instance;

  private SingletonLazy() {
    System.out.println("> create instance (!)");
  }

  public static SingletonLazy getInstance() {
    if (instance == null) {
      // created only when needed
      instance = new SingletonLazy();
    }
    return instance;
  }

  public void helloSingleton() {
    System.out.println("Hello! I'm a singleton.");
  }

  public static void main(String[] args) {
    System.out.println("> program start");
    SingletonLazy.getInstance().helloSingleton();
    System.out.println("> program finish");
  }

  // Output
  // > program start
  // > create instance (!)
  // Hello! I'm a singleton.
  // > program finish
}
  • Lusta, de szálbiztos megoldás:
 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
/**
 * Thread-safe singleton with lazy instantiation.
 */
public class SingletonLazyThreadSafe {

  private static SingletonLazyThreadSafe instance;

  private SingletonLazyThreadSafe() {
  }

  // ------------------- VERSION SIMPLE >> -----------------------
  // just use synchronized on the getter method
  // + simple method
  // - bad performance because of sync checking
  public static synchronized SingletonLazyThreadSafe getInstanceSimple() {
    if (instance == null) {
      instance = new SingletonLazyThreadSafe();
    }
    return instance;
  }
  // ------------------- << VERSION SIMPLE -----------------------

  // ------------------- VERSION BETTER >> -----------------------
  // only the creation of the instance is synchronized
  private static synchronized void createInstance() {
    if (instance == null) { // double check because of thread magic
      instance = new SingletonLazyThreadSafe();
    }
  }

  // no synchronized needed
  // - a bit more complex
  // + good performance, no sync checking needed
  public static SingletonLazyThreadSafe getInstanceBetter() {
    if (instance == null) {
      createInstance();
    }
    return instance;
  }
  // ------------------- << VERSION BETTER -----------------------

  public void helloSingleton() {
    System.out.println("Hello! I'm a singleton.");
  }
}
  • Egy másik lusta, de szálbiztos megoldás
 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
package hu.u_szeged.inf.ovrt.singleton;

public class SingletonLazyThreadSafe2 {
  private int num = 0;

  private SingletonLazyThreadSafe2() {
  }

  public static SingletonLazyThreadSafe2 getInstance() {
    return SingletonSampleHolder.INSTANCE;
  }

  public void helloSingleton() {
    System.out.println("Hello was said " + ++num + " times");
  }

  // Threadsafe !!
  private static class SingletonSampleHolder {
    private static final SingletonLazyThreadSafe2 INSTANCE = new SingletonLazyThreadSafe2();
  }

  public static void main(String[] args) {
    SingletonLazyThreadSafe2 inst1 = SingletonLazyThreadSafe2.getInstance();
    inst1.helloSingleton();

    SingletonLazyThreadSafe2 inst2 = SingletonLazyThreadSafe2.getInstance();
    inst2.helloSingleton();

    System.out.println(inst1 == inst2);
  }
}
  • Enum megoldás (thread safe, egyszerű, jól áttekinthető)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * Singleton implemented as an enum.
 * 
 * + easy implementation <br>
 * + thread-safe <br>
 * ~ early initialization <br>
 * - no inheritance <br>
 */
public enum SingletonEnum {

  INSTANCE;

  public void helloSingleton() {
    System.out.println("Hello! I'm a singleton.");
  }


  //// MAIN ////
  public static void main(String[] args) {
    SingletonEnum.INSTANCE.helloSingleton();
  }
}

Null object

NEM GOF MINTA

1
2
3
4
5
6
7
public abstract class AbstractWizard {
  protected String name;

  public abstract boolean isNull();

  public abstract String getName();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class RealWizard extends AbstractWizard {

  public RealWizard(String name) {
    this.name = name;
  }

  @Override
  public String getName() {
    return name;
  }

  @Override
  public boolean isNull() {
    return false;
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class NullWizard extends AbstractWizard {

  @Override
  public String getName() {
    return "The customer does not exists";
  }

  @Override
  public boolean isNull() {
    return true;
  }
}
1
2
3
4
5
6
7
import java.util.List;

public interface DatabaseInterface {
  public List<AbstractWizard> getWizards();

  public AbstractWizard getWizardByName(String name);
}
 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
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class FakeDatabase implements DatabaseInterface {
  public static final String[] availableWizards = { "harry", "ron", "hermione" };

  @Override
  public List<AbstractWizard> getWizards() {
    List<AbstractWizard> Wizards = new ArrayList<>();

    for (String name : availableWizards) {
      Wizards.add(new RealWizard(name));
    }

    return Collections.unmodifiableList(Wizards);
  }

  @Override
  public AbstractWizard getWizardByName(String name) {
    if (Arrays.asList(availableWizards).contains(name.toLowerCase())) {
      return new RealWizard(name);
    }
    return new NullWizard();
  }

  // Singleton
  private FakeDatabase() {

  }

  public static final FakeDatabase getInstance() {
    return FakeDatabaseHolder.INSTANCE;
  }

  private static class FakeDatabaseHolder {
    private static final FakeDatabase INSTANCE = new FakeDatabase();
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import java.util.Scanner;

public class NullObjectDemo {

  private static final DatabaseInterface db = FakeDatabase.getInstance();
  private static final Scanner scanner = new Scanner(System.in);

  public static void main(String[] args) {
    System.out.println("Kezdjuk el! Kit kersz az adatbazisbol?");

    String ans = scanner.nextLine();
    while (!"exit".equals(ans)) {

      AbstractWizard Wizard = db.getWizardByName(ans);

      System.out.println("Neve: " + Wizard.getName());
      System.out.println("Letezo vassarlo? " + (Wizard.isNull() ? "nem" : "igen"));
      ans = scanner.nextLine();
    }
  }
}

Feladatok

A projekthez kötődően ismerkedés, csapatalakítás.


Utolsó frissítés: 2021-09-29 12:54:00