Kamusta! Ngayon ay patuloy nating pag-aaralan ang mga pattern ng disenyo at pag-uusapan ang abstract factory . Ano ang gagawin natin sa lecture:
- Talakayin natin kung ano ang abstract factory at kung anong problema ang nalulutas ng pattern na ito;
- gagawa kami ng balangkas ng isang cross-platform na application para sa pag-order ng kape na may user interface;
- Pag-aralan natin ang mga tagubilin para sa paggamit ng pattern na ito na may diagram at code;
- Bilang isang bonus, mayroong isang Easter egg na nakatago sa lecture, salamat sa kung saan matututunan mong matukoy ang pangalan ng operating system gamit ang Java at, depende sa resulta, magsagawa ng isa o isa pang aksyon.
- mana sa Java;
- abstract na mga klase at pamamaraan sa Java.
Anong mga problema ang nalulutas ng abstract factory pattern?
Ang abstract na pabrika, tulad ng lahat ng mga pattern ng pabrika, ay tumutulong sa amin na ayusin ang paglikha ng mga bagong bagay nang tama. Sa tulong nito, pinamamahalaan namin ang "paglabas" ng iba't ibang pamilya ng magkakaugnay na mga bagay. Iba't ibang pamilya ng magkakaugnay na bagay...Ano ito? Huwag mag-alala: sa pagsasagawa, ang lahat ay mas simple kaysa sa tila. Magsimula tayo sa kung ano ang maaaring isang pamilya ng mga kaugnay na bagay? Ipagpalagay na ikaw at ako ay bumubuo ng isang diskarte, at mayroong ilang mga yunit ng labanan sa loob nito:- impanterya;
- kabalyerya;
- mga mamamana.
Patuloy naming ginagawang awtomatiko ang coffee shop
Sa huling panayam, pinag-aralan namin ang pattern ng factory method, sa tulong kung saan napalawak namin ang negosyo ng kape at nagbukas ng ilang mga bagong punto ng pagbebenta ng kape. Ngayon ay ipagpapatuloy natin ang ating gawain para gawing 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 sumulat tayo ng isang application para sa desktop, dapat nating palaging isipin ang tungkol sa cross-platform. Ang aming application ay dapat gumana sa parehong macOS at Windows (spoiler: Ang Linux ay iiwan para sa iyo bilang araling-bahay). Ano ang magiging hitsura ng aming aplikasyon? Medyo simple: ito ay magiging isang form na binubuo ng isang text field, isang piling field, at isang button. Kung mayroon kang karanasan sa paggamit ng iba't ibang mga operating system, tiyak na napansin mo na sa Windows ang mga pindutan ay nai-render nang iba kaysa sa Mac. Tulad ng lahat ng iba pa... Kaya, magsimula tayo. Sa papel ng mga pamilya ng produkto, tulad ng malamang na naunawaan mo na, magkakaroon kami ng mga elemento ng graphical na interface:- mga pindutan;
- mga patlang ng teksto;
- mga patlang para sa pagpili.
onClick
, onValueChanged
o onInputChanged
. Yung. mga pamamaraan na magpapahintulot sa amin na pangasiwaan ang iba't ibang mga kaganapan (pag-click sa isang pindutan, pagpasok ng teksto, pagpili ng isang halaga sa isang piling kahon). Ang lahat ng ito ay sadyang tinanggal upang hindi ma-overload ang halimbawa at gawin itong mas visual para sa pag-aaral ng 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 na iyon. Nagsusulat kami 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 ay pareho para sa MacOS:
public class MacButton implements Button {
}
public class MacSelect implements Select {
}
public class MacTextField implements TextField {
}
Malaki. Ngayon ay maaari na nating simulan ang aming abstract factory, na lilikha ng lahat ng umiiral na abstract na uri ng produkto:
public interface GUIFactory {
Button createButton();
TextField createTextField();
Select createSelect();
}
Perpekto. Tulad ng nakikita mo, walang kumplikado sa ngayon. Kung gayon ang lahat ay kasing simple. Sa pamamagitan ng pagkakatulad sa mga produkto, gumagawa kami ng iba't ibang pagpapatupad ng aming pabrika para sa bawat OS. Magsimula tayo sa Windows:
public class WindowsGUIFactory implements GUIFactory {
public WindowsGUIFactory() {
System.out.println("Creating gui factory 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();
}
}
Ang output ng console sa loob ng mga pamamaraan at constructor ay idinagdag upang higit pang ipakita kung paano ito gumagana. Ngayon para sa macOS:
public class MacGUIFactory implements GUIFactory {
public MacGUIFactory() {
System.out.println("Creating gui factory 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: ang bawat pamamaraan, ayon sa lagda nito, ay nagbabalik ng abstract na uri. Ngunit sa loob ng pamamaraan ay lumikha kami ng isang kongkretong pagpapatupad ng produkto. Ito ang tanging lugar kung saan kinokontrol namin ang paglikha ng mga partikular na pagkakataon. Ngayon ay oras na upang isulat ang klase ng form. Ito ay isang klase ng Java na ang mga patlang ay mga elemento ng interface:
public class OrderCoffeeForm {
private final TextField customerNameTextField;
private final Select coffeTypeSelect;
private final Button orderButton;
public OrderCoffeeForm(GUIFactory factory) {
System.out.println("Creating order coffee form");
customerNameTextField = factory.createTextField();
coffeTypeSelect = factory.createSelect();
orderButton = factory.createButton();
}
}
Ang abstract factory ay ipinapasa sa form constructor, na lumilikha ng mga elemento ng interface. Ipapasa namin ang kinakailangang pagpapatupad ng pabrika sa constructor upang makagawa kami ng mga elemento ng interface para sa isang partikular na OS.
public class Application {
private OrderCoffeeForm orderCoffeeForm;
public void drawOrderCoffeeForm() {
// Определим Name операционной системы, получив meaning системной проперти через System.getProperty
String osName = System.getProperty("os.name").toLowerCase();
GUIFactory guiFactory;
if (osName.startsWith("win")) { // Для windows
guiFactory = new WindowsGUIFactory();
} else if (osName.startsWith("mac")) { // Для mac
guiFactory = new MacGUIFactory();
} else {
System.out.println("Unknown OS, can't draw form :( ");
return;
}
orderCoffeeForm = new OrderCoffeeForm(guiFactory);
}
public static void main(String[] args) {
Application application = new Application();
application.drawOrderCoffeeForm();
}
}
Kung patakbuhin namin ang application sa Windows, makukuha namin ang sumusunod na output:
Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
Sa isang Mac ang output ay magiging tulad ng sumusunod:
Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
Sa Linux:
Unknown OS, can't draw form :(
Buweno, ikaw at ako ay gumuhit ng sumusunod na konklusyon. Sumulat kami ng isang framework para sa isang GUI application na lumilikha ng eksaktong mga elemento ng interface na naaangkop para sa isang partikular na OS. Ulitin natin sandali ang ating nilikha:
- Pamilya ng produkto: field ng input, field ng pagpili at button.
- Iba't ibang pagpapatupad ng pamilyang ito ng mga produkto, para sa Windows at macOS.
- Isang abstract factory, kung saan tinukoy namin ang 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 klase ng Java na ang mga field ay abstract na mga elemento ng interface na sinisimulan sa constructor na may mga kinakailangang halaga gamit ang abstract factory.
- Klase ng aplikasyon. Sa loob nito, lumikha kami ng isang form kung saan ipinapasa namin ang kinakailangang pagpapatupad ng aming pabrika sa tagabuo.
Abstract Factory: mga tagubilin para sa paggamit
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 partikular na klase ng produkto. Kapag ginagamit ang template na ito, dapat mong:- Tukuyin ang mga pamilya ng produkto mismo. Ipagpalagay natin na mayroon tayong dalawa sa kanila:
SpecificProductA1
,SpecificProductB1
SpecificProductA2
,SpecificProductB2
- Para sa bawat produkto sa loob ng pamilya, tumukoy ng abstract na klase (interface). Sa aming kaso ito ay:
ProductA
ProductB
- Sa loob ng bawat pamilya ng produkto, dapat ipatupad ng bawat produkto ang interface na tinukoy sa hakbang 2.
- Lumikha ng abstract factory, na may mga paraan ng paggawa para sa bawat produkto na tinukoy sa hakbang 2. Sa aming kaso, ang mga paraang ito ay:
ProductA createProductA();
ProductB createProductB();
- Gumawa ng mga pagpapatupad ng abstract factory upang kontrolin ng bawat pagpapatupad ang paglikha ng mga produkto ng parehong pamilya. Upang gawin ito, sa loob ng bawat pagpapatupad ng abstract na pabrika, kinakailangan na ipatupad ang lahat ng mga pamamaraan ng paglikha, upang ang mga kongkretong pagpapatupad ng mga produkto ay nilikha at ibinalik sa loob ng mga ito.
// Определим общие интерфейсы продуктов
public interface ProductA {}
public interface ProductB {}
// Создадим различные реализации (семейства) наших продуктов
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}
public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}
// Создадим абстрактную фабрику
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA1();
}
@Override
public ProductB createProductB() {
return new SpecificProductB1();
}
}
// Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
public class SpecificFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA2();
}
@Override
public ProductB createProductB() {
return new SpecificProductB2();
}
}
Takdang aralin
Upang pagsamahin ang materyal maaari kang gumawa ng 2 bagay:- Pagbutihin ang application ng pag-order ng kape upang gumana ito sa Linux.
- Lumikha ng iyong sariling abstract na pabrika upang makagawa ng mga yunit ng anumang diskarte. Maaari itong maging isang makasaysayang diskarte sa mga tunay na hukbo o isang pantasya sa mga orc, dwarf at duwende. Ang pangunahing bagay ay nahanap mo itong kawili-wili. Maging malikhain, mag-post ng mga pin sa console, at magsaya sa pag-aaral ng mga pattern!
GO TO FULL VERSION