Már áttekintettük a singleton objektumok használatát, de lehet, hogy még nem veszi észre, hogy ez a stratégia tervezési minta, és az egyik leggyakrabban használt.

Valójában nagyon sok ilyen minta létezik, és céljuk szerint osztályozhatók.

Minta osztályozás

Mintatípus Alkalmazás
Kreatív Egy típus, amely megoldja az objektum létrehozási problémát
Szerkezeti Minták, amelyek segítségével helyes és bővíthető osztályhierarchiát építhetünk fel architektúránkban
Viselkedési Ez a mintacsoport biztonságos és kényelmes interakciót tesz lehetővé a program objektumai között.

A mintát jellemzően az általa megoldott probléma jellemzi. Vessünk egy pillantást néhány mintára, amelyekkel leggyakrabban találkozunk, amikor Java-val dolgozunk:

Minta Célja
Szingli Már ismerjük ezt a mintát – egy olyan osztály létrehozására és elérésére használjuk, amelynek nem lehet több példánya.
Iterátor Ezt is ismerjük. Tudjuk, hogy ez a minta lehetővé teszi, hogy egy gyűjteményobjektum felett iteráljunk anélkül, hogy felfednénk annak belső reprezentációját. Gyűjteményekhez használják.
Adapter Ez a minta összekapcsolja az inkompatibilis objektumokat, hogy együtt tudjanak működni. Azt hiszem, az adapterminta neve segít elképzelni, hogy ez pontosan mit is csinál. Íme egy egyszerű példa a való életből: USB adapter fali aljzathoz.
Sablon módszer

Egy viselkedési programozási minta, amely megoldja az integrációs problémát, és lehetővé teszi az algoritmus lépéseinek megváltoztatását anélkül, hogy megváltoztatná az algoritmus szerkezetét.

Képzeljük el, hogy van egy autó-összeszerelési algoritmusunk az összeszerelési lépések sorozata formájában:

Alváz -> Karosszéria -> Motor -> Fülke belső

Ha megerősített vázat, erősebb motort vagy kiegészítő világítással ellátott belsőt teszünk bele, akkor nem kell az algoritmust módosítanunk, és az absztrakt sorrend változatlan marad.

Lakberendező Ez a minta burkolókat hoz létre az objektumokhoz, hogy hasznos funkciókat biztosítson nekik. Ezt a cikk részeként fogjuk figyelembe venni.

A Java.io-ban a következő osztályok valósítanak meg mintákat:

Minta Hol használják a java.io-ban
Adapter
Sablon módszer
Lakberendező

Dekorátor minta

Képzeljük el, hogy egy lakberendezési modellt írunk le.

Általában a megközelítés így néz ki:

Kezdetben többféle háztípus közül válogathatunk. A minimális konfiguráció egy emelet tetővel. Ezután mindenféle lakberendezőt használunk további paraméterek megváltoztatására, ami természetesen befolyásolja a ház árát.

Létrehozunk egy absztrakt House osztályt:


public abstract class House {
	String info;
 
	public String getInfo() {
    	return info;
	}
 
	public abstract int getPrice();
}
    

Itt van 2 módszerünk:

  • A getInfo() információkat ad vissza házunk nevéről és jellemzőiről;
  • A getPrice() az aktuális házkonfiguráció árát adja vissza.

Vannak szabványos házmegvalósításaink is – tégla és fa:


public class BrickHouse extends House {
 
	public BrickHouse() {
    	info = "Brick House";
	}
 
	@Override
	public int getPrice() {
    	return 20_000;
	}
}
 
public class WoodenHouse extends House {
 
	public WoodenHouse() {
    	info = "Wooden House";
	}
 
	@Override
	public int getPrice() {
    	return 25_000;
	}
}
    

Mindkét osztály örökli a Ház osztályt, és felülírja annak ármódszerét, egyéni árat állítva be egy standard házhoz. Beállítjuk a nevet a konstruktorban.

Ezután dekorátor órákat kell írnunk. Ezek az osztályok a House osztályt is öröklik . Ehhez létrehozunk egy absztrakt dekoratőr osztályt.

Itt további logikát helyezünk el egy objektum megváltoztatásához. Kezdetben nem lesz további logika, és az absztrakt osztály üres lesz.


abstract class HouseDecorator extends House {
}
    

Ezután dekorátor megvalósításokat készítünk. Több osztályt hozunk létre, amelyek segítségével további funkciókat adhatunk a házhoz:


public class SecondFloor extends HouseDecorator {
	House house;
 
	public SecondFloor(House house) {
    	this.house = house;
	}
 
	@Override
	public int getPrice() {
    	return house.getPrice() + 20_000;
	}
 
	@Override
	public String getInfo() {
    	return house.getInfo() + " + second floor";
	}
}
    
Egy lakberendező, aki második emelettel bővíti házunkat

A lakberendező kivitelező olyan házat fogad el, amit mi "bedíszítünk", azaz módosítunk. És felülírjuk a getPrice() és getInfo() metódusokat, és a régi alapján adunk vissza információkat az új frissített házról.


public class Garage extends HouseDecorator {
 
	House house;
	public Garage(House house) {
    	this.house = house;
	}
 
	@Override
	public int getPrice() {
    	return house.getPrice() + 5_000;
	}
 
	@Override
	public String getInfo() {
    	return house.getInfo() + " + garage";
	}
}
    
Egy lakberendező, aki garázzsal bővíti házunkat

Most már lakberendezőkkel is felfrissíthetjük házunkat. Ehhez létre kell hoznunk egy házat:


House brickHouse = new BrickHouse();
    

Ezután beállítjuk a sajátunkatházváltozó megegyezik egy új lakberendezővel, ami házunkban megy el:


brickHouse = new SecondFloor(brickHouse); 
    

A miénkházváltozó most egy második emeletes ház.

Nézzük a lakberendezők felhasználási eseteit:

Példa kód Kimenet

House brickHouse = new BrickHouse(); 

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());
                    

Téglaház

20000


House brickHouse = new BrickHouse(); 

  brickHouse = new SecondFloor(brickHouse); 

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());
                    

Tégla ház + második emelet

40000


House brickHouse = new BrickHouse();
 

  brickHouse = new SecondFloor(brickHouse);
  brickHouse = new Garage(brickHouse);

  System.out.println(brickHouse.getInfo());
  System.out.println(brickHouse.getPrice());
                    

Tégla ház + második emelet + garázs

45000


House woodenHouse = new SecondFloor(new Garage(new WoodenHouse())); 

  System.out.println(woodenHouse.getInfo());
  System.out.println(woodenHouse.getPrice());
                    

Faház + garázs + második emelet

50000


House woodenHouse = new WoodenHouse(); 

  House woodenHouseWithGarage = new Garage(woodenHouse);

  System.out.println(woodenHouse.getInfo());
  System.out.println(woodenHouse.getPrice());

  System.out.println(woodenHouseWithGarage.getInfo());
  System.out.println(woodenHouseWithGarage.getPrice());
                    

Faház

25000

Faház + garázs

30000

Ez a példa szemlélteti egy objektum dekorátorral történő frissítésének előnyeit. Tehát nem változtattunkfaházmagát az objektumot, hanem egy új objektumot hozott létre a régi alapján. Itt láthatjuk, hogy az előnyöknek hátrányai is vannak: minden alkalommal új objektumot hozunk létre a memóriában, növelve a memóriafelhasználást.

Tekintse meg programunk UML diagramját:

A dekoratőr rendkívül egyszerű megvalósítással rendelkezik, és dinamikusan változtatja az objektumokat, frissíti azokat. A dekorátorokat a konstruktorok ismerhetik fel, amelyek paraméterként az aktuális osztályéval azonos absztrakt típusú vagy interfész objektumokat vesznek fel. A Java nyelven ezt a mintát széles körben használják az I/O osztályokban.

Például, ahogy már említettük, a java.io.InputStream , OutputStream , Reader és Writer összes alosztályának van egy konstruktora, amely elfogadja az azonos osztályú objektumokat.