Sa puntong ito, malamang na nakatagpo ka na ng mga pattern ng disenyo. Halimbawa, singleton .

Alalahanin natin kung ano ang mga pattern, bakit kailangan ang mga ito, at kung ano ang mga pattern ng paglikha (isang halimbawa ang singleton). Mag-aaral din tayo ng bagong pattern: ang factory method.

Sa pagbuo ng software, ang isang pattern ng disenyo ay isang paulit-ulit na konstruksyon ng arkitektura na kumakatawan sa isang solusyon sa isang problema sa disenyo sa loob ng ilang umuulit na konteksto.

Karaniwan, ang isang pattern ay hindi isang pangwakas na solusyon na maaaring direktang i-convert sa code. Isa lamang itong modelong solusyon sa isang problema na magagamit sa iba't ibang sitwasyon.

Ang mga pattern ng paglikha ay mga pattern ng disenyo na tumatalakay sa proseso ng paglikha ng mga bagay. Ginagawa nilang posible na lumikha ng isang sistema na independiyente sa paraan na ginamit upang lumikha, bumuo, at magpakita ng mga bagay.

Ang factory method ay isang creational design pattern na tumutukoy sa isang karaniwang interface para sa paglikha ng mga object sa isang parent class, na nagbibigay sa mga descendant nito ng kakayahang lumikha ng mga object na ito. Sa oras ng paglikha, matutukoy ng mga inapo kung aling klase ang gagawin.

Anong problema ang nalulutas ng pattern?

Isipin na nagpasya kang lumikha ng isang programa sa paghahatid. Sa una, kukuha ka ng mga courier na may mga sasakyan at gagamit ng akotsetumutol na kumatawan sa isang sasakyan sa paghahatid sa programa. Ang mga courier ay naghahatid ng mga pakete mula sa point A hanggang point B at iba pa. Napakadali.

Ang programa ay nakakakuha ng katanyagan. Lumalago ang iyong negosyo at gusto mong palawakin sa mga bagong merkado. Halimbawa, maaari mo ring simulan ang paghahatid ng pagkain at pagpapadala ng kargamento. Sa kasong ito, ang pagkain ay maaaring ihatid ng mga courier sa paglalakad, sa mga scooter, at sa mga bisikleta, ngunit ang mga trak ay kailangan para sa kargamento.

Ngayon ay kailangan mong subaybayan ang ilang bagay (kailan, kanino, ano at magkano ang ihahatid), kabilang ang kung magkano ang maaaring dalhin ng bawat courier. Ang mga bagong paraan ng transportasyon ay may iba't ibang bilis at kapasidad. Pagkatapos ay mapapansin mo na ang karamihan sa mga entity sa iyong programa ay mahigpit na nakatali sakotseklase. Napagtanto mo na upang gumana ang iyong programa sa iba pang mga paraan ng paghahatid, kakailanganin mong muling isulat ang umiiral nang code base at gawin iyon muli sa tuwing magdaragdag ka ng bagong sasakyan.

Ang resulta ay nakakatakot na code na puno ng mga conditional statement na nagsasagawa ng iba't ibang mga aksyon depende sa uri ng transportasyon.

Ang solusyon

Ang pattern ng factory method ay nagmumungkahi ng paglikha ng mga bagay sa pamamagitan ng pagtawag sa isang espesyal na factory method sa halip na direktang gamit ang bagong operator. Maaaring baguhin ng mga subclass ng klase na mayroong factory method ang mga nilikhang bagay ng mga partikular na sasakyan. Sa unang sulyap, ito ay maaaring mukhang walang kabuluhan: inilipat lang namin ang tawag ng constructor mula sa isang lugar sa programa patungo sa isa pa. Ngunit ngayon ay maaari mong i-override ang factory method sa isang subclass para baguhin ang uri ng transportasyong ginagawa.

Tingnan natin ang class diagram para sa diskarteng ito:

Para gumana ang system na ito, ang lahat ng ibinalik na bagay ay dapat magkaroon ng isang karaniwang interface. Ang mga subclass ay makakagawa ng mga object ng iba't ibang klase na nagpapatupad ng interface na ito.

Halimbawa, ipinapatupad ng mga klase ng Truck at Car ang interface ng CourierTransport na may paraan ng paghahatid . Ang bawat isa sa mga klase na ito ay nagpapatupad ng pamamaraan sa ibang paraan: ang mga trak ay naghahatid ng kargamento, habang ang mga kotse ay naghahatid ng pagkain, mga pakete, at iba pa. Ang factory method sa TruckCreator class ay nagbabalik ng truck object, at ang CarCreator class ay nagbabalik ng car object.

Para sa kliyente ng pamamaraan ng pabrika, walang pagkakaiba sa pagitan ng mga bagay na ito, dahil ituturing nito ang mga ito bilang ilang uri ng abstract CourierTransport . Ang kliyente ay lubos na nagmamalasakit na ang bagay ay may isang paraan para sa paghahatid, ngunit kung paano eksaktong gumagana ang pamamaraang iyon ay hindi mahalaga.

Pagpapatupad sa Java:


public interface CourierTransport {
	void deliver();
}
public class Car implements CourierTransport {
	@Override
	public void deliver() {
    		System.out.println("The package is being delivered by car");
	}
}
public class Truck implements CourierTransport {
	@Override
	public void deliver() {
    		System.out.println("The freight is being delivered by truck");
	}
}
public abstract class CourierTransportCreator {
	public abstract CourierTransport createTransport();
}
public class CarCreator extends CourierTransportCreator {
	@Override
	public CourierTransport createTransport() {
    		return new Car();
	}
}
public class TruckCreator extends CourierTransportCreator {
	@Override
	public CourierTransport createTransport() {
    		return new Truck();
	}
}
 
public class Delivery {
	private String address;
	private CourierTransport courierTransport;
 
	public void Delivery() {
	}
 
	public Delivery(String address, CourierTransport courierTransport) {
    	this.address = address;
    	this.courierTransport = courierTransport;
	}
 
	public CourierTransport getCourierTransport() {
    		return courierTransport;
	}
 
	public void setCourierTransport(CourierTransport courierTransport) {
    		this.courierTransport = courierTransport;
	}
 
	public String getAddress() {
    		return address;
	}
 
	public void setAddress(String address) {
    		this.address = address;
	}
}
public static void main(String[] args) {
    	// Accept a new type of order from the database (pseudocode)
    	String type = database.getTypeOfDeliver();
 
    	Delivery delivery = new Delivery();
    	
    	// Set the transport for delivery
        delivery.setCourierTransport(getCourierTransportByType(type));
    	
    	// Make the delivery
        delivery.getCourierTransport().deliver();
 
	}
 
	public static CourierTransport getCourierTransportByType(String type) {
    	switch (type) {
        	case "CarDelivery":
            	return new CarCreator().createTransport();
        	case "TruckDelivery":
            	return new TruckCreator().createTransport();
        	default:
            	throw new RuntimeException();
	    }
	}
    

Kung gusto naming lumikha ng isang bagong bagay sa paghahatid, pagkatapos ay awtomatikong lumilikha ang programa ng isang naaangkop na bagay sa transportasyon.

Kailan natin dapat ilapat ang pattern na ito?

1. Kapag hindi mo alam nang maaga ang mga uri at dependency ng mga bagay na kailangan ng iyong code upang gumana.

Ang pamamaraan ng pabrika ay naghihiwalay sa code para sa paggawa ng mga paraan ng transportasyon mula sa code na gumagamit ng transportasyon. Bilang resulta, ang code para sa paglikha ng mga bagay ay maaaring palawigin nang hindi hinahawakan ang natitirang bahagi ng code.

Halimbawa, upang magdagdag ng suporta para sa isang bagong uri ng transportasyon, kailangan mong gumawa ng bagong subclass at tukuyin ang isang factory method dito na nagbabalik ng isang instance ng bagong transportasyon.

2. Kapag gusto mong i-save ang mga mapagkukunan ng system sa pamamagitan ng muling paggamit ng mga umiiral na bagay sa halip na lumikha ng mga bago.

Karaniwang nangyayari ang problemang ito kapag nagtatrabaho sa mga bagay na masinsinang mapagkukunan, tulad ng mga koneksyon sa database, mga file system, atbp.

Isipin ang mga hakbang na kailangan mong gawin upang muling magamit ang mga umiiral na bagay:

  1. Una, kailangan mong lumikha ng isang nakabahaging imbakan upang maiimbak ang lahat ng mga bagay na iyong nilikha.

  2. Kapag humihiling ng bagong bagay, kailangan mong tumingin sa repositoryo at suriin kung naglalaman ito ng magagamit na bagay.

  3. Ibalik ang object sa client code.

  4. Ngunit kung walang magagamit na mga bagay, lumikha ng bago at idagdag ito sa repositoryo.

Ang lahat ng code na ito ay kailangang ilagay sa isang lugar na hindi makakalat sa client code. Ang pinaka-maginhawang lugar ay ang constructor, dahil kailangan lang namin ang lahat ng mga pagsusuring ito kapag lumilikha ng mga bagay. Sa kasamaang palad, ang isang constructor ay palaging lumilikha ng isang bagong bagay - hindi nito maibabalik ang isang umiiral na bagay.

Nangangahulugan iyon na kailangan ng isa pang paraan na maaaring magbalik ng mga dati at bagong bagay. Ito ang magiging paraan ng pabrika.

3. Kapag gusto mong payagan ang mga user na i-extend ang mga bahagi ng iyong framework o library.

Maaaring i-extend ng mga user ang iyong mga framework class sa pamamagitan ng inheritance. Ngunit paano mo gagawin ang balangkas na lumikha ng mga bagay ng mga bagong klase na ito kaysa sa mga karaniwang?

Ang solusyon ay hayaan ang mga user na palawigin hindi lamang ang mga bahagi, kundi pati na rin ang mga klase na lumikha ng mga bahaging iyon. At para dito, ang paglikha ng mga klase ay dapat magkaroon ng mga tiyak na paraan ng paglikha na maaaring tukuyin.

Mga kalamangan

  • Nag-decouples ng isang klase mula sa mga partikular na klase sa transportasyon.
  • Pinapanatili ang code para sa paglikha ng mga paraan ng transportasyon sa isang lugar, na ginagawang mas madaling mapanatili ang code.
  • Pinapasimple ang pagdaragdag ng mga bagong paraan ng transportasyon sa programa.
  • Ipinapatupad ang prinsipyong bukas-sarado.

Mga disadvantages

Maaaring humantong sa malalaking parallel class hierarchies, dahil ang bawat klase ng produkto ay dapat may sarili nitong creator subclass.

I-summarize natin

Natutunan mo ang tungkol sa pattern ng factory method at nakakita ng isang posibleng pagpapatupad. Ang pattern na ito ay kadalasang ginagamit sa iba't ibang mga aklatan na nagbibigay ng mga bagay para sa paglikha ng iba pang mga bagay.

Gamitin ang pattern ng factory method kapag gusto mong madaling magdagdag ng mga bagong object ng mga subclass ng mga umiiral nang klase upang makipag-ugnayan sa iyong pangunahing logic sa negosyo at hindi ma-bloat ang iyong code dahil sa iba't ibang konteksto.