Nasuri na namin ang paggamit ng singleton object, ngunit maaaring hindi mo pa napagtanto na ang diskarteng ito ay isang pattern ng disenyo, at isa sa pinakaginagamit noon.

Sa katunayan, maraming mga pattern na ito, at maaari silang uriin ayon sa kanilang partikular na layunin.

Pag-uuri ng pattern

Uri ng pattern Aplikasyon
Malikhain Isang uri na lumulutas sa problema sa paglikha ng bagay
Structural Mga pattern na nagbibigay-daan sa amin na bumuo ng tama at napapalawak na hierarchy ng klase sa aming arkitektura
Pag-uugali Ang kumpol ng mga pattern na ito ay nagpapadali sa ligtas at maginhawang pakikipag-ugnayan sa pagitan ng mga bagay sa isang programa.

Karaniwan, ang isang pattern ay nailalarawan sa pamamagitan ng problemang nalulutas nito. Tingnan natin ang ilang mga pattern na madalas nating nararanasan kapag nagtatrabaho sa Java:

Pattern Layunin
Singleton Pamilyar na kami sa pattern na ito — ginagamit namin ito para gumawa at mag-access ng klase na hindi maaaring magkaroon ng higit sa isang instance.
Tagapag-ulit Pamilyar din kami sa isang ito. Alam namin na ang pattern na ito ay nagbibigay-daan sa amin na umulit sa isang koleksyon na bagay nang hindi inilalantad ang panloob na representasyon nito. Ginagamit ito sa mga koleksyon.
Adapter Ang pattern na ito ay nag-uugnay sa mga hindi tugmang bagay upang sila ay magtulungan. Sa tingin ko ang pangalan ng pattern ng adaptor ay nakakatulong sa iyo na isipin kung ano mismo ang ginagawa nito. Narito ang isang simpleng halimbawa mula sa totoong buhay: isang USB adapter para sa isang saksakan sa dingding.
Paraan ng template

Isang pattern ng behavioral programming na lumulutas sa problema sa pagsasama at nagbibigay-daan sa iyong baguhin ang mga algorithmic na hakbang nang hindi binabago ang istraktura ng isang algorithm.

Isipin na mayroon kaming algorithm ng pagpupulong ng kotse sa anyo ng isang pagkakasunud-sunod ng mga hakbang sa pagpupulong:

Chassis -> Katawan -> Engine -> Interior ng Cabin

Kung maglalagay kami ng isang reinforced frame, isang mas malakas na makina, o isang interior na may karagdagang ilaw, hindi namin kailangang baguhin ang algorithm, at ang abstract sequence ay nananatiling pareho.

Dekorador Ang pattern na ito ay lumilikha ng mga wrapper para sa mga bagay upang bigyan sila ng kapaki-pakinabang na pag-andar. Isasaalang-alang natin ito bilang bahagi ng artikulong ito.

Sa Java.io, ang mga sumusunod na klase ay nagpapatupad ng mga pattern:

Pattern Kung saan ito ginagamit sa java.io
Adapter
Paraan ng template
Dekorador

Pattern ng dekorador

Isipin natin na naglalarawan tayo ng isang modelo para sa disenyo ng bahay.

Sa pangkalahatan, ang diskarte ay ganito:

Sa una, mayroon kaming pagpipilian ng ilang uri ng mga bahay. Ang pinakamababang pagsasaayos ay isang palapag na may bubong. Pagkatapos ay ginagamit namin ang lahat ng uri ng mga dekorador upang baguhin ang mga karagdagang parameter, na natural na nakakaapekto sa presyo ng bahay.

Lumilikha kami ng abstract na klase ng House:


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

Narito mayroon kaming 2 pamamaraan:

  • getInfo() ay nagbabalik ng impormasyon tungkol sa pangalan at mga tampok ng aming bahay;
  • ibinabalik ng getPrice() ang presyo ng kasalukuyang configuration ng bahay.

Mayroon din kaming karaniwang mga pagpapatupad ng Bahay — ladrilyo at kahoy:


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;
	}
}
    

Ang parehong klase ay nagmamana ng klase ng House at na-override ang paraan ng presyo nito, na nagtatakda ng custom na presyo para sa isang karaniwang bahay. Itinakda namin ang pangalan sa tagabuo.

Susunod, kailangan nating magsulat ng mga klase ng dekorador. Ang mga klaseng ito ay magmamana rin ng klase ng House . Upang gawin ito, lumikha kami ng isang abstract na klase ng dekorador.

Doon tayo maglalagay ng karagdagang lohika para sa pagbabago ng isang bagay. Sa una, walang karagdagang lohika at ang abstract na klase ay magiging walang laman.


abstract class HouseDecorator extends House {
}
    

Susunod, lumikha kami ng mga pagpapatupad ng dekorador. Gagawa kami ng ilang klase na nagbibigay-daan sa amin na magdagdag ng mga karagdagang feature sa bahay:


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";
	}
}
    
Isang dekorador na nagdaragdag ng pangalawang palapag sa aming bahay

Ang tagabuo ng dekorador ay tumatanggap ng isang bahay na aming "palamutihan", ibig sabihin, magdagdag ng mga pagbabago. At in-override namin ang getPrice() at getInfo() na mga pamamaraan, na nagbabalik ng impormasyon tungkol sa bagong na-update na bahay batay sa luma.


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";
	}
}
    
Isang dekorador na nagdaragdag ng garahe sa aming bahay

Ngayon ay maaari naming i-update ang aming bahay sa mga dekorador. Upang gawin ito, kailangan nating lumikha ng isang bahay:


House brickHouse = new BrickHouse();
    

Susunod, itinakda namin ang amingbahayvariable na katumbas ng isang bagong dekorador, na dumadaan sa aming bahay:


brickHouse = new SecondFloor(brickHouse); 
    

Ang amingbahayAng variable ay isang bahay na ngayon na may pangalawang palapag.

Tingnan natin ang mga kaso ng paggamit na kinasasangkutan ng mga dekorador:

Halimbawang code Output

House brickHouse = new BrickHouse(); 

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

Brick House

20000


House brickHouse = new BrickHouse(); 

  brickHouse = new SecondFloor(brickHouse); 

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

Brick House + second floor

40000


House brickHouse = new BrickHouse();
 

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

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

Brick House + second floor + garahe

45000


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

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

Wooden House + garahe + second floor

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

Bahay na Kahoy

25000

Bahay na kahoy + garahe

30000

Ang halimbawang ito ay naglalarawan ng benepisyo ng pag-upgrade ng isang bagay gamit ang isang dekorador. Kaya hindi namin binago angkahoy na Bahayobject mismo, ngunit sa halip ay lumikha ng isang bagong object batay sa luma. Dito makikita natin na ang mga pakinabang ay may kasamang mga disadvantages: gumagawa tayo ng bagong bagay sa memorya sa bawat oras, na nagpapataas ng pagkonsumo ng memorya.

Tingnan ang diagram ng UML na ito ng aming programa:

Ang isang dekorador ay may napakasimpleng pagpapatupad at dynamic na nagbabago ng mga bagay, na ina-upgrade ang mga ito. Ang mga dekorador ay maaaring makilala ng kanilang mga konstruktor, na kumukuha bilang mga parameter ng mga bagay ng parehong abstract na uri o interface bilang kasalukuyang klase. Sa Java, ang pattern na ito ay malawakang ginagamit sa mga klase ng I/O.

Halimbawa, tulad ng nabanggit na natin, ang lahat ng mga subclass ng java.io.InputStream , OutputStream , Reader at Writer ay may constructor na tumatanggap ng mga object ng parehong klase.