JavaRush /Kurslar /All lectures for UZ purposes /Loyiha Namunalari. Dekorator

Loyiha Namunalari. Dekorator

All lectures for UZ purposes
Daraja, Dars
Mavjud

Biz allaqachon Singleton kabi sinf obyektini ishlatish sxemasidan o'tdik, lekin balki sen hali bilmasliging mumkin, lekin bu loyihalash namunalardan biri, eng ko'p qo'llaniladiganlaridan biri.

Darhaqiqat juda ko'p turli xildagi namunalari bor, undan tashqari - ular o'z iyerarxiyasiga ega va har bir namunani o'z maqsadi bor.

Patternlar Klassifikatsiyasi

Pattern turi Qo'llanishi
Yaratish Obyektlar yaratish muammosini hal qiluvchi tur
Strukturaviy Bizning arxitekturamizda to'g'ri, kengayishga mos iyerarxiyani qurish imkonini beradigan naqshlar
Xulq-atvorga oid Bu klaster naqshlari dastur ob'ektlari o'rtasida xavfsiz va qulay aloqani qabul qiladi

Odatda pattern hal qiladigan muammo bilan xarakterlanadi. Keling, Java bilan ishlashda eng ko'p duch keladigan namunalarni ko'rib chiqaylik:

Pattern Maqsad
Singleton Biz allaqachon tanishmiz va uni bitta nusxada bo'lishi mumkin emas bo'lgan sinf yaratish va murojaat qilish uchun ishlatamiz.
Iterator Biz, asosan, tanishmiz va bilamizki, ushbu pattern bizga ichki ko'rinishini ochmasdan tarkibini aytishga imkon beradi. To'plamlar bilan ishlatiladi.
Adapter Birgalikda ishlash uchun noto'g'ri ob'ektlarni bog'lash. O'ylaymanki, adapter haqida gapirganda har bir kishi aynan nima qiladigan patternni anglatayotganini tasavvur qiladi. Hayotdan oddiy misol - USB adapter - vilka rozetkaga.
Template Method

Dasturlash uslubidan biri bo'lib, integratsiya muammosini hal qiladi va algoritmning tuzilishini o'zgartirmasdan uning qadamlarini o'zgartiradi.

Avtomobil yig'ish algoritmi bir ketma ketlikda yig'ilishini tasavvur qilaylik:

Shassi -> Korpus -> Motor -> salon yig'ish

Agar biz kuchli ramka, kuchli motor yoki qo'shimcha yoritish bilan salon qo'ysak ham, algoritmni o'zgartirmaymiz, va abstrakt ketma-ketlik o'sha qoladi.

Decorator Ob'ektlarga qo'shimcha foydali funktsionallik qo'shish uchun o'ramlarni yaratadi. Uni biz ushbu maqola kontekstida ko'rib chiqamiz.

Java.io da patternlar quyidagi sinflarda amalga oshiriladi:

Dekorator Patterni

Uy loyihalash modelini tasavvur qilaylik.

Umumiy sxema quyidagicha bo'ladi:

Dastlab bizda bir necha turdagi uy tanlovi bor. Minimal konfiguratsiya - bitta qavat va tom, keyinchalik - dekortorlar yordamida har qanday turdagi qo'shimcha parametrlar bilan o'zgartirilishi mumkin va bu uy narxiga ta'sir qiladi.

Abstrakt uy sinfini yaratamiz:


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

Bu yerda bizda 2 usul bor:

  • getInfo() uy nomi va konfiguratsiyasi haqida ma'lumotni qaytaradi;
  • getPrice() — uy narxini joriy konfiguratsiyada.

Shuningdek, bizda odatiy uy implemetatsiyalari bor - g'ishtli va yog'ochdan yasalgan:


public class BrickHouse extends House {
 
	public BrickHouse() {
    	info = "G'ishtli uy";
	}
 
	@Override
	public int getPrice() {
    	return 20_000;
	}
}
 
public class WoodenHouse extends House {
 
	public WoodenHouse() {
    	info = "Yog'och uy";
	}
 
	@Override
	public int getPrice() {
    	return 25_000;
	}
}
    

Ikkala sinf ham House sinfidan meros olgan va narx metodini qayta yozib, standart uy uchun individual narx belgilaydi. Konstruktorida ismni tayinlaymiz.

Keyin biz dekorator sinflarini yozishimiz kerak. Bular House sinfidan ham meros olgan sinflardir. Buning uchun biz dekoratsiya qilishning abstrakt sinfini yaratamiz.

Biz unga ob'ektni o'zgartirish uchun qo'shimcha mantiq qo'shishimiz mumkin. Bizning holatda qo'shimcha mantiq bo'lmaydi va abstrakt sinf bo'sh qoladi.


abstract class HouseDecorator extends House {
}
    

Keyin dekoratorlarni amalga oshirish sinflarini yaratamiz. Biz bir nechta sinflarni yaratamiz, bu uylarga qo'shimcha parametrlar qo'shishga imkon beradi:


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() + " + ikkinchi qavat";
	}
}
    
Bizning uyga ikkinchi qavat qo'shadigan dekorator

Dekoratorda uy qabul qilinadi, unga dekoratordan o'zgarishlar qo'llaymiz. Usullar getPrice() va getInfo()ni qayta yozamiz, eski uydan yaratilgan yangi modernizatsiyalangan uy haqida ma'lumotni qaytarish.


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() + " + garaj";
	}
}
    
Uyga garaj qo'shadigan dekorator

Endi biz uyni dekoratorlar yordamida o'zgartirishimiz mumkin. Buning uchun uy yaratish kerak:


House brickHouse = new BrickHouse();
    

Keyin bizning house o'zgaruvchisiga yangi qiymat tayinlaymiz, bu bizning uyimizni uzatamiz:


brickHouse = new SecondFloor(brickHouse); 
    

Bizning house o'zgaruvchimiz allaqachon ikkinchi qavatli uyga ega.

Keling dekoratorlar ishlatiladigan holatlarni ko'rib chiqaylik:

Kod namunasi Natija

House brickHouse = new BrickHouse(); 

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

G'ishtli uy

20000


House brickHouse = new BrickHouse(); 

  brickHouse = new SecondFloor(brickHouse); 

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

G'ishtli uy + ikkinchi qavat

40000


House brickHouse = new BrickHouse();
 

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

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

G'ishtli uy + ikkinchi qavat + garaj

45000


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

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

Yog'och uy + garaj + ikkinchi qavat

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());
                    

Yog'och uy

25000

Yog'och uy + garaj

30000

Ushbu misolda biz dekorator yordamida ob'ektni yangilashning afzalligini ko'ramiz. Ko'rinib turibdiki, biz woodenHouse ob'ektini o'zgartirmadik, lekin yangi ob'ekt yaratdik. Ammo bu afzallik orqali, biz har safar yangi ob'ekt yaratib, xotiraga qo'shimcha yuklamalar qo'shamiz.

Bizning dasturimizning UML diagrammasini ko'rib chiqaylik:

Dekorator nisbatan oson amalga oshiriladi va ob'ektlarni dinamik o'zgartirish, ularni modernizatsiya qilish uchun qo'llaniladi. Dekoratorni parametrlarida o'sha abstrakt tur yoki interfeysdagi ob'ektlarni qabul qiladigan konstruktorlar orqali aniqlash mumkin. Java'da ushbu pattern keng tarqalgan holda kirish/chiqish sinflarida qo'llaniladi.

Masalan, biz allaqachon ta'kidlab o'tdik, barcha java.io.InputStream, OutputStream, Reader va Writer sinflari o'sha sinflarning ob'ektlarini qabul qiladigan konstruktoriga ega.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION