Vid det hÀr laget har du förmodligen redan stött pÄ designmönster. Till exempel singleton .

LÄt oss komma ihÄg vad mönster Àr, varför de behövs och vad skapande mönster Àr (singleton Àr ett exempel). Vi ska ocksÄ studera ett nytt mönster: fabriksmetoden.

Inom mjukvaruutveckling Àr ett designmönster en repeterbar arkitektonisk konstruktion som representerar en lösning pÄ ett designproblem inom nÄgot Äterkommande sammanhang.

Vanligtvis Àr ett mönster inte en slutlig lösning som direkt kan konverteras till kod. Det Àr bara en modelllösning pÄ ett problem som kan anvÀndas i olika situationer.

Skapande mönster Àr designmönster som handlar om processen att skapa objekt. De gör det möjligt att skapa ett system som Àr oberoende av den metod som anvÀnds för att skapa, komponera och presentera objekt.

En fabriksmetod Àr ett kreativt designmönster som definierar ett gemensamt grÀnssnitt för att skapa objekt i en överordnad klass, vilket ger dess avkomlingar möjlighet att skapa dessa objekt. Vid skapandet kan efterkommande bestÀmma vilken klass som ska skapas.

Vilket problem löser mönstret?

FörestÀll dig att du bestÀmmer dig för att skapa ett leveransprogram. Till en början kommer du att hyra kurirer med bilar och anvÀnda enBilobjekt för att representera ett leveransfordon i programmet. Bud levererar paket frÄn punkt A till punkt B och sÄ vidare. LÀtt som en plÀtt.

Programmet ökar i popularitet. Ditt företag vÀxer och du vill expandera till nya marknader. Du kan till exempel börja Àven leverera mat och fraktfrakt. I det hÀr fallet kan mat levereras av bud till fots, pÄ skotrar och pÄ cyklar, men lastbilar behövs för frakt.

Nu behöver du hÄlla reda pÄ flera saker (nÀr, till vem, vad och hur mycket som kommer att levereras), inklusive hur mycket varje bud kan bÀra. De nya transportsÀtten har olika hastigheter och kapacitet. DÄ mÀrker du att de flesta enheter i ditt program Àr starkt knutna tillBilklass. Du inser att för att fÄ ditt program att fungera med andra leveransmetoder mÄste du skriva om den befintliga kodbasen och göra det igen varje gÄng du lÀgger till ett nytt fordon.

Resultatet Àr fruktansvÀrd kod fylld med villkorliga uttalanden som utför olika ÄtgÀrder beroende pÄ typen av transport.

Lösningen

Fabriksmetodmönstret föreslÄr att man skapar objekt genom att anropa en speciell fabriksmetod istÀllet för att direkt anvÀnda den nya operatorn. Underklasser av klassen som har fabriksmetoden kan modifiera de skapade objekten för de specifika fordonen. Vid första anblicken kan detta verka meningslöst: vi har helt enkelt flyttat konstruktoranropet frÄn en plats i programmet till en annan. Men nu kan du ÄsidosÀtta fabriksmetoden i en underklass för att Àndra typen av transport som skapas.

LÄt oss titta pÄ klassdiagrammet för detta tillvÀgagÄngssÀtt:

För att detta system ska fungera mÄste alla returnerade objekt ha ett gemensamt grÀnssnitt. Underklasser kommer att kunna producera objekt av olika klasser som implementerar detta grÀnssnitt.

Till exempel implementerar klasserna Truck och Car CourierTransport- grÀnssnittet med en leveransmetod . Var och en av dessa klasser implementerar metoden pÄ olika sÀtt: lastbilar levererar frakt, medan bilar levererar mat, paket och sÄ vidare. Fabriksmetoden i TruckCreator -klassen returnerar ett lastbilsobjekt och CarCreator -klassen returnerar ett bilobjekt.

För klienten av fabriksmetoden Àr det ingen skillnad mellan dessa objekt, eftersom det kommer att behandla dem som nÄgon form av abstrakt CourierTransport . Kunden kommer att bry sig mycket om att objektet har en metod för att leverera, men hur exakt den metoden fungerar Àr inte viktigt.

Implementering i 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();
	    }
	}
    

Om vi ​​vill skapa ett nytt leveransobjekt skapar programmet automatiskt ett lĂ€mpligt transportobjekt.

NÀr ska vi tillÀmpa detta mönster?

1. NÀr du inte i förvÀg vet vilka typer och beroenden av objekten som din kod behöver arbeta med.

Fabriksmetoden skiljer koden för att producera transportformer frÄn koden som anvÀnder transporten. Som ett resultat kan koden för att skapa objekt utökas utan att röra resten av koden.

Till exempel, för att lÀgga till stöd för en ny typ av transport, mÄste du skapa en ny underklass och definiera en fabriksmetod i den som returnerar en instans av den nya transporten.

2. NÀr du vill spara systemresurser genom att ÄteranvÀnda befintliga objekt istÀllet för att skapa nya.

Detta problem uppstÄr vanligtvis nÀr man arbetar med resurskrÀvande objekt, som databasanslutningar, filsystem, etc.

TÀnk pÄ de steg du behöver ta för att ÄteranvÀnda befintliga objekt:

  1. Först mÄste du skapa ett delat arkiv för att lagra alla objekt du skapar.

  2. NÀr du begÀr ett nytt objekt mÄste du titta i förvaret och kontrollera om det innehÄller ett tillgÀngligt objekt.

  3. Returnera objektet till klientkoden.

  4. Men om det inte finns nÄgra tillgÀngliga objekt, skapa ett nytt och lÀgg till det i förvaret.

All den hĂ€r koden mĂ„ste placeras nĂ„gonstans som inte belamrar klientkoden. Den mest bekvĂ€ma platsen skulle vara konstruktören, eftersom vi bara behöver alla dessa kontroller nĂ€r vi skapar objekt. TyvĂ€rr skapar en konstruktör alltid ett nytt objekt — den kan inte returnera ett befintligt objekt.

Det betyder att det behövs en annan metod som kan returnera bÄde befintliga och nya objekt. Detta kommer att vara fabriksmetoden.

3. NÀr du vill tillÄta anvÀndare att utöka delar av ditt ramverk eller bibliotek.

AnvÀndare kan utöka dina ramklasser genom arv. Men hur fÄr man ramverket att skapa objekt av dessa nya klasser snarare Àn de vanliga?

Lösningen Àr att lÄta anvÀndare utöka inte bara komponenterna, utan Àven klasserna som skapar dessa komponenter. Och för detta mÄste de skapande klasserna ha specifika skapandemetoder som kan definieras.

Fördelar

  • Frikopplar en klass frĂ„n specifika transportklasser.
  • HĂ„ller koden för att skapa transportformer pĂ„ ett stĂ€lle, vilket gör koden lĂ€ttare att underhĂ„lla.
  • Förenklar tillĂ€gget av nya transportsĂ€tt till programmet.
  • Implementerar öppet-stĂ€ngt-principen.

Nackdelar

Kan leda till stora parallella klasshierarkier, eftersom varje produktklass mÄste ha sin egen skaparunderklass.

LĂ„t oss sammanfatta

Du lÀrde dig om fabriksmetodens mönster och sÄg en möjlig implementering. Detta mönster anvÀnds ofta i olika bibliotek som tillhandahÄller objekt för att skapa andra objekt.

AnvÀnd fabriksmetoden nÀr du enkelt vill lÀgga till nya objekt av underklasser av befintliga klasser för att interagera med din huvudsakliga affÀrslogik och inte svÀlla din kod pÄ grund av olika sammanhang.