
Java programátor expert
Dnes sa pozrieme na ďalší návrhový vzor Flyweight (java design patterns) z kategórie štrukturálnych vzorov (structural patterns). Návrhové vzory v tejto kategórii sa zaoberajú štruktúrou triedy, ako je dedičnosť (inheritance) a kompozícia (composition).
Flyweight je návrhový vzor, ktorý sa primárne používa na zníženie počtu vytvorených objektov, pretože sa pokúša znova použiť už existujúce objekty s rovnakými alebo podobnými vlastnosťami na úrovni triedy a nový objekt vytvorí až vtedy, keď sa nenájde žiadny zodpovedajúci objekt. Tým sa minimalizuje množstvo využívanej pamäte pre údaje zdieľanými medzi podobnými objektami.
Rieši problém v aplikáciách, ktoré pracujú s veľkým počtom objektov, ktoré by pri samostatnom uložení zaberali množstvo pamäte a nezanedbateľné sú aj náklady na ich vytváranie. Tento vzor rieši problém tak, že spoločné dáta sa extrahujú a zdieľajú medzi objektami, čím sa znižuje množstvo potrebnej pamäte a využívajú sa už vytvorené objekty.
Teraz si napíšeme program, ktorý bude simulovať jednoduchý systém na prevádzku pizzerie a na ňom si demonštrujeme práve použitie návrhového vzoru Flyweight na efektívne zdieľanie inštancií pízz a minimalizáciu počtu vytvorených objektov. Program vytvára pizzeriu, prijíma objednávky rôznych druhov pízz a obsluhuje ich. Bude pozostávať z tried Pizza, Objednavka a Pizzeria a Main.
Pizza.java
package designpatterns;
import java.util.HashMap;
import java.util.Map;
public class Pizza {
private static Map<String, Pizza> pizzaCache = new HashMap<>();
private String nazov;
private Pizza(String nazov) {
this.nazov = nazov;
}
public static Pizza intern(String nazov) {
pizzaCache.putIfAbsent(nazov, new Pizza(nazov));
return pizzaCache.get(nazov);
}
public static int pocetDruhov() {
return pizzaCache.size();
}
@Override
public String toString() {
return nazov;
}
}
Trieda Pizza reprezentuje druh pizzy a využíva vzor Flyweight na zdieľanie inštancií pízz s rovnakým názvom. Má metódu intern(), ktorá vytvára novú pizzu len v prípade, ak ešte neexistuje, a metódu pocetDruhov(), ktorá vracia počet rôznych druhov pízz.
Objednavka.java
package designpatterns;
public class Objednavka {
private Pizza pizza;
private int cisloStolu;
private Objednavka(Pizza pizza, int cisloStolu) {
this.pizza = pizza;
this.cisloStolu = cisloStolu;
}
public static Objednavka create(String nazov, int cisloStolu) {
Pizza pizza = Pizza.intern(nazov);
return new Objednavka(pizza, cisloStolu);
}
@Override
public String toString() {
return "Posielam pizzu " + pizza + " na stol " + cisloStolu;
}
}
Trieda Objednavka reprezentuje objednávku pizzy. Každá objednávka obsahuje odkaz na konkrétnu pizzu a číslo stolu, kam má byť pizza doručená.
Pizzeria.java
package designpatterns;
public class Pizzeria {
private java.util.List<Objednavka> objednavky = new java.util.ArrayList<>();
public void prijatObjednavku(String druh, int cisloStolu) {
objednavky.add(Objednavka.create(druh, cisloStolu));
}
public void obsluzit() {
for (Objednavka order : objednavky) {
System.out.println(order);
}
}
public int pocetPrijatychObjednavok() {
return objednavky.size();
}
}
Trieda Pizzeria predstavuje pizzeriu, ktorá prijíma objednávky a poskytuje metódy na spracovanie a výpis objednávok. Taktiež poskytuje metódu na získanie počtu prijatých objednávok.
Main.java
import designpatterns.Pizzeria;
import designpatterns.Pizza;
public class Main {
public static void main(String[] args) {
Pizzeria pizzeria = new Pizzeria();
pizzeria.prijatObjednavku("Hawai", 2);
pizzeria.prijatObjednavku("Quattro Formaggi", 1);
pizzeria.prijatObjednavku("Margherita", 1);
pizzeria.prijatObjednavku("Napoletana", 5);
pizzeria.prijatObjednavku("Hawai", 4);
pizzeria.prijatObjednavku("Quattro Formaggi", 3);
pizzeria.prijatObjednavku("Margherita", 3);
pizzeria.prijatObjednavku("Hawai", 3);
pizzeria.prijatObjednavku("Margherita", 6);
pizzeria.prijatObjednavku("Quattro Formaggi", 2);
pizzeria.obsluzit();
System.out.println();
System.out.println("Pocet prijatych objednavok: " + pizzeria.pocetPrijatychObjednavok());
System.out.println("Pocet pouzitych objektov typu pizza: " + Pizza.pocetDruhov());
}
}
V metóde main je vytvorená inštancia pizzerie a potom sú vytvorené rôzne objednávky na pizze. Všetky objednávky sú obslúžené a nakoniec sa vypíše počet prijatých objednávok a počet použitých objektov typu Pizza. Tým sme preukázali zdieľanie objektov typu Pizza medzi rozdielnymi objednávkami.
Výstup z tohto príkladu je:
Návrhový vzor Flyweight sa používa v situácii, keď potrebujeme ukladať do vyrovnávacej pamäte a opätovne využívať inštancie objektov, ktoré sú si podobné. Je zameraný najmä na optimalizovanie réžie vytvárania objektov a ich nárokov na pamäť.
Pripravili sme pre teba súbory so spomínaným príkladom vo forme kódu, ktorý si môžeš spustiť priamo v Jave. Stiahni si kód Java Flyweight tu.
Ak si Java programátor a hľadáš prácu, pozri si naše firemné benefity a reaguj na najnovšie pracovné ponuky.