CodeGym/Java Blog/Random/Mga pattern ng disenyo: Abstract na pabrika
John Squirrels
Antas
San Francisco

Mga pattern ng disenyo: Abstract na pabrika

Nai-publish sa grupo
Hi! Ngayon ay patuloy nating pag-aaralan ang mga pattern ng disenyo at tatalakayin natin ang abstract factory pattern. Mga pattern ng disenyo: Abstract na pabrika - 1Narito ang tatalakayin natin sa aralin:
  • Tatalakayin natin kung ano ang abstract factory at kung anong problema ang nalulutas ng pattern na ito
  • Gagawa kami ng skeleton ng isang cross-platform na application para sa pag-order ng kape sa pamamagitan ng user interface
  • Pag-aaralan namin ang mga tagubilin kung paano gamitin ang pattern na ito, kabilang ang pagtingin sa isang diagram at code
  • At bilang isang bonus, ang araling ito ay may kasamang isang nakatagong Easter egg na tutulong sa iyo na matutunan kung paano gamitin ang Java upang matukoy ang pangalan ng operating system at, depende sa resulta, upang magsagawa ng isa't isa na aksyon o iba pa.
Upang lubos na maunawaan ang pattern na ito, kailangan mong maging bihasa sa mga sumusunod na paksa:
  • mana sa Java
  • abstract na mga klase at pamamaraan sa Java

Anong mga problema ang nalulutas ng abstract factory?

Ang isang abstract na pabrika, tulad ng lahat ng mga pattern ng pabrika, ay tumutulong sa amin upang matiyak na ang mga bagong bagay na gagawin nang tama. Ginagamit namin ito upang pamahalaan ang "produksyon" ng iba't ibang pamilya ng magkakaugnay na mga bagay. Iba't ibang pamilya ng magkakaugnay na bagay... Ano ang ibig sabihin nito? Huwag mag-alala: sa pagsasagawa, ang lahat ay mas simple kaysa sa tila. Upang magsimula, ano ang maaaring maging isang pamilya ng magkakaugnay na mga bagay? Ipagpalagay na bubuo tayo ng diskarteng militar na kinasasangkutan ng ilang uri ng mga yunit:
  • impanterya
  • kabalyerya
  • mga mamamana
Ang mga uri ng mga yunit ay magkakaugnay, dahil sila ay naglilingkod sa parehong hukbo. Maaari naming sabihin na ang mga kategoryang nakalista sa itaas ay isang pamilya ng magkakaugnay na mga bagay. Naiintindihan namin ito. Ngunit ang abstract na pattern ng pabrika ay ginagamit upang ayusin ang paglikha ng iba't ibang mga pamilya ng magkakaugnay na mga bagay. Wala rin namang kumplikado dito. Ipagpatuloy natin ang halimbawa ng diskarte sa militar. Sa pangkalahatan, ang mga yunit ng militar ay nabibilang sa ilang magkakaibang partidong naglalabanan. Depende sa kung kaninong panig sila ay nasa, ang mga yunit ng militar ay maaaring mag-iba nang malaki sa hitsura. Ang mga foot soldiers, horsemen at archers ng Roman army ay hindi katulad ng Viking foot soldiers, horsemen at archers. Sa diskarte ng militar, ang mga sundalo ng iba't ibang hukbo ay magkakaibang pamilya ng magkakaugnay na mga bagay. Nakakatuwa kung ang isang programmer' Ang pagkakamali ay naging sanhi ng isang kawal na nakasuot ng unipormeng Pranses sa panahon ng Napoleon, na nakahanda na, na matagpuang naglalakad sa hanay ng impanterya ng Roma. Ang abstract na pattern ng disenyo ng pabrika ay kinakailangan nang tumpak para sa paglutas ng problemang ito. Hindi, hindi ang problema ng kahihiyan na maaaring magmula sa paglalakbay sa oras, ngunit ang problema ng paglikha ng iba't ibang grupo ng magkakaugnay na mga bagay. Ang abstract factory ay nagbibigay ng isang interface para sa paglikha ng lahat ng magagamit na mga produkto (isang pamilya ng mga bagay). Karaniwang mayroong maraming pagpapatupad ang abstract factory. Ang bawat isa sa kanila ay may pananagutan sa paglikha ng mga produkto ng isa sa mga pamilya. Kasama sa aming diskarte sa militar ang abstract factory na lumilikha ng abstract foot soldiers, archers, at cavalrymen, pati na rin ang mga pagpapatupad ng factory na ito. Halimbawa, isang pabrika na lumilikha ng mga Roman legionnaires at isang pabrika na lumilikha ng mga sundalong Carthaginian. Ang abstraction ang pinakamahalagang gabay na prinsipyo ng pattern na ito. Ang mga kliyente ng pabrika ay nagtatrabaho sa pabrika at sa mga produkto nito sa pamamagitan lamang ng mga abstract na interface. Bilang resulta, hindi mo na kailangang isipin kung sinong mga sundalo ang kasalukuyang nililikha. Sa halip, ipinapasa mo ang responsibilidad na ito sa ilang konkretong pagpapatupad ng abstract factory.

Ipagpatuloy natin ang pag-automate ng ating coffee shop

Sa huling aralin, pinag-aralan namin ang pattern ng factory method. Ginamit namin ito upang palawakin ang aming negosyo sa kape at magbukas ng ilang bagong lokasyon. Ngayon, patuloy nating gagawing moderno ang ating negosyo. Gamit ang abstract factory pattern, ilalagay namin ang pundasyon para sa isang bagong desktop application para sa pag-order ng kape online. Kapag nagsusulat ng isang desktop application, dapat nating palaging isipin ang tungkol sa cross-platform na suporta. Ang aming application ay dapat gumana sa parehong macOS at Windows (spoiler: Ang suporta para sa Linux ay natitira para sa iyo upang ipatupad bilang araling-bahay). Ano ang magiging hitsura ng aming aplikasyon? Medyo simple: ito ay magiging isang form na binubuo ng isang text field, isang selection field, at isang button. Kung mayroon kang karanasan sa paggamit ng iba't ibang mga operating system, tiyak na napansin mo na ang mga button sa Windows ay nai-render nang iba kaysa sa isang Mac. Tulad ng lahat ng iba pa... Well, magsimula tayo.
  • mga pindutan
  • mga patlang ng teksto
  • mga patlang ng pagpili
Disclaimer: Sa bawat interface, maaari naming tukuyin ang mga pamamaraan tulad ng onClick, onValueChanged, o onInputChanged. Sa madaling salita, maaari naming tukuyin ang mga pamamaraan na magpapahintulot sa amin na pangasiwaan ang iba't ibang mga kaganapan (pagpindot sa isang pindutan, pagpasok ng teksto, pagpili ng isang halaga sa isang kahon ng pagpili). Ang lahat ng ito ay sadyang tinanggal dito upang hindi ma-overload ang halimbawa at upang maging mas malinaw habang pinag-aaralan natin ang pattern ng pabrika. Tukuyin natin ang mga abstract na interface para sa ating mga produkto:
public interface Button {}
public interface Select {}
public interface TextField {}
Para sa bawat operating system, dapat tayong lumikha ng mga elemento ng interface sa istilo ng operating system. Magsusulat kami ng code para sa Windows at MacOS. Gumawa tayo ng mga pagpapatupad para sa Windows:
public class WindowsButton implements Button {
}

public class WindowsSelect implements Select {
}

public class WindowsTextField implements TextField {
}
Ngayon ginagawa namin ang parehong para sa MacOS:
public class MacButton implements Button {
}

public class MacSelect implements Select {
}

public class MacTextField implements TextField {
}
Magaling. Ngayon ay maaari na tayong magpatuloy sa aming abstract factory, na gagawa ng lahat ng available na abstract na uri ng produkto:
public interface GUIFactory {

    Button createButton();
    TextField createTextField();
    Select createSelect();

}
Napakagaling. Tulad ng nakikita mo, wala pa kaming ginagawang kumplikado. Ang lahat ng sumusunod ay simple din. Sa pamamagitan ng pagkakatulad sa mga produkto, lumikha kami ng iba't ibang mga pagpapatupad ng pabrika para sa bawat OS. Magsimula tayo sa Windows:
public class WindowsGUIFactory implements GUIFactory {
    public WindowsGUIFactory() {
        System.out.println("Creating GUIFactory for Windows OS");
    }

    public Button createButton() {
        System.out.println("Creating Button for Windows OS");
        return new WindowsButton();
    }

    public TextField createTextField() {
        System.out.println("Creating TextField for Windows OS");
        return new WindowsTextField();
    }

    public Select createSelect() {
        System.out.println("Creating Select for Windows OS");
        return new WindowsSelect();
    }
}
Nagdagdag kami ng ilang console output sa loob ng mga pamamaraan at constructor upang higit pang mailarawan kung ano ang nangyayari. Ngayon para sa macOS:
public class MacGUIFactory implements GUIFactory {
    public MacGUIFactory() {
        System.out.println("Creating GUIFactory for macOS");
    }

    @Override
    public Button createButton() {
        System.out.println("Creating Button for macOS");
        return new MacButton();
    }

    @Override
    public TextField createTextField() {
        System.out.println("Creating TextField for macOS");
        return new MacTextField();
    }

    @Override
    public Select createSelect() {
        System.out.println("Creating Select for macOS");
        return new MacSelect();
    }
}
Tandaan na ang bawat lagda ng pamamaraan ay nagpapahiwatig na ang pamamaraan ay nagbabalik ng isang abstract na uri. Ngunit sa loob ng mga pamamaraan, gumagawa kami ng mga partikular na pagpapatupad ng mga produkto. Ito ang tanging lugar na kinokontrol namin ang paglikha ng mga partikular na pagkakataon. Ngayon ay oras na upang magsulat ng isang klase para sa form. Ito ay isang klase ng Java na ang mga patlang ay mga elemento ng interface:
public class CoffeeOrderForm {
    private final TextField customerNameTextField;
    private final Select coffeeTypeSelect;
    private final Button orderButton;

    public CoffeeOrderForm(GUIFactory factory) {
        System.out.println("Creating coffee order form");
        customerNameTextField = factory.createTextField();
        coffeeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
Ang abstract factory na lumilikha ng mga elemento ng interface ay ipinapasa sa constructor ng form. Ipapasa namin ang kinakailangang pagpapatupad ng pabrika sa constructor upang makalikha ng mga elemento ng interface para sa isang partikular na OS.
public class Application {
    private CoffeeOrderForm coffeeOrderForm;

    public void drawCoffeeOrderForm() {
        // Determine the name of the operating system through System.getProperty()
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // For Windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // For Mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS. Unable to draw form :(");
            return;
        }
        coffeeOrderForm = new CoffeeOrderForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawCoffeeOrderForm();
    }
}
Kung patakbuhin namin ang application sa Windows, makukuha namin ang sumusunod na output:
Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Sa isang Mac, ang output ay ang mga sumusunod:
Creating GUIFactory for macOS
Creating coffee order form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Sa Linux:
Unknown OS. Unable to draw form :(
At ngayon ay nagbubuod tayo. Isinulat namin ang skeleton ng isang GUI-based na application kung saan ang mga elemento ng interface ay partikular na nilikha para sa nauugnay na OS. Ulitin namin nang maikli ang aming nilikha:
  • Isang pangkat ng produkto na binubuo ng isang input field, isang selection field, at isang button.
  • Iba't ibang pagpapatupad ng pamilya ng produkto para sa Windows at macOS.
  • Isang abstract na pabrika na tumutukoy sa isang interface para sa paggawa ng aming mga produkto.
  • Dalawang pagpapatupad ng aming pabrika, bawat isa ay may pananagutan sa paglikha ng isang partikular na pamilya ng mga produkto.
  • Isang form (isang Java class) na ang mga field ay abstract na mga elemento ng interface na sinisimulan gamit ang mga kinakailangang value sa constructor gamit ang abstract factory.
  • Klase ng aplikasyon Sa loob ng klase na ito, lumikha kami ng isang form, na ipinapasa ang nais na pagpapatupad ng pabrika sa tagabuo nito.
Ang resulta ay ipinatupad namin ang abstract factory pattern.

Abstract factory: kung paano gamitin

Ang abstract factory ay isang pattern ng disenyo para sa pamamahala ng paglikha ng iba't ibang pamilya ng produkto nang hindi nakatali sa mga kongkretong klase ng produkto. Kapag ginagamit ang pattern na ito, dapat mong:
  1. Tukuyin ang mga pamilya ng produkto. Ipagpalagay na mayroon tayong dalawa sa kanila:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. Para sa bawat produkto sa loob ng pamilya, tumukoy ng abstract na klase (interface). Sa aming kaso, mayroon kaming:
    • ProductA
    • ProductB
  3. Sa loob ng bawat pamilya ng produkto, dapat ipatupad ng bawat produkto ang interface na tinukoy sa hakbang 2.
  4. Lumikha ng abstract na pabrika, na may mga pamamaraan para sa paglikha ng bawat produkto na tinukoy sa hakbang 2. Sa aming kaso, ang mga pamamaraang ito ay magiging:
    • ProductA createProductA();
    • ProductB createProductB();
  5. Gumawa ng abstract na mga pagpapatupad ng pabrika upang kontrolin ng bawat pagpapatupad ang paglikha ng mga produkto ng isang pamilya. Upang gawin ito, sa loob ng bawat pagpapatupad ng abstract na pabrika, kailangan mong ipatupad ang lahat ng mga pamamaraan ng paglikha upang lumikha at magbalik sila ng mga partikular na pagpapatupad ng produkto.
Ang sumusunod na diagram ng UML ay naglalarawan ng mga tagubiling nakabalangkas sa itaas: Mga pattern ng disenyo: Abstract na pabrika - 3Ngayon ay magsusulat kami ng code ayon sa mga tagubiling ito:
// Define common product interfaces
public interface ProductA {}
public interface ProductB {}

// Create various implementations (families) of our products
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}

public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}

// Create an abstract factory
public interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// Implement the abstract factory in order to create products in family 1
public class SpecificFactory1 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA1();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB1();
    }
}

// Implement the abstract factory in order to create products in family 2
public class SpecificFactory2 implements AbstractFactory {

    @Override
    public ProductA createProductA() {
        return new SpecificProductA2();
    }

    @Override
    public ProductB createProductB() {
        return new SpecificProductB2();
    }
}

Takdang aralin

Upang palakasin ang materyal, maaari kang gumawa ng 2 bagay:
  1. Pinuhin ang application ng pag-order ng kape upang gumana rin ito sa Linux.
  2. Lumikha ng iyong sariling abstract na pabrika para sa paggawa ng mga yunit na kasangkot sa anumang diskarte sa militar. Maaari itong maging isang makasaysayang diskarte sa militar na kinasasangkutan ng mga tunay na hukbo, o isang pantasya na may mga orc, gnome, at duwende. Ang mahalagang bagay ay pumili ng isang bagay na interesado ka. Maging malikhain, mag-print ng mga mensahe sa console, at mag-enjoy sa pag-aaral tungkol sa mga pattern!
Mga komento
  • Sikat
  • Bago
  • Luma
Dapat kang naka-sign in upang mag-iwan ng komento
Wala pang komento ang page na ito