
工廠方法模式(Factory Method)
工廠方法模式(Factory Method)是一種創(chuàng)建型的設(shè)計(jì)模式,在該模式中父類決定實(shí)例的生成方式。但是不決定它要生成的具體的類,具體的處理是交給子類完成的,這樣將生成實(shí)例的框架和負(fù)責(zé)生成實(shí)例的類解耦。
接下來通過一個(gè)制作身份證明的IDCard來學(xué)習(xí)工廠方法模式,照例先來一張類圖,對(duì)該例程序有大概的認(rèn)識(shí)。
類圖:
產(chǎn)品類Product
Product屬于工廠方法模式中的"產(chǎn)品"類,在該類中僅僅聲明了一個(gè)抽象方法use(),定義了任意產(chǎn)品都可以u(píng)se的方法,即定義了生成的實(shí)例所持有的接口方法。
public abstract class Product {
public abstract void use();
}
工廠類Factory
該類是生產(chǎn)Product的類,該類內(nèi)部提供了一個(gè)create方法創(chuàng)建產(chǎn)品,并且提供抽象方法createProduct創(chuàng)建產(chǎn)品和registerProduct注冊(cè)產(chǎn)品。他在工廠方法模式充當(dāng)創(chuàng)建者這一角色,負(fù)責(zé)生成產(chǎn)品Product,但是具體處理交由具體創(chuàng)建者。對(duì)于使用生成實(shí)例的專用方法createProduct創(chuàng)建實(shí)例,而不用new關(guān)鍵字來生成,這樣做的好處是可以防止
父類與其他類耦合。
public abstract class Factory {
public final Product create(String owner) {
Product p = createProduct(owner);
registerProduct(p);
return p;
}
protected abstract Product createProduct(String owner);
protected abstract void registerProduct(Product product);
}
具體產(chǎn)品類IDCard
在上面說到產(chǎn)品類Product,它需要子類去實(shí)現(xiàn)具體的產(chǎn)品IDCard,而IDCard和Product是分離的。
public class IDCard extends Product {
private String owner;
IDCard(String owner) {
System.out.println("制作ID卡"+owner);
this.owner = owner;
}
public void use() {
System.out.println("使用ID卡"+owner);
}
public String getOwner() {
return owner;
}
}
具體工廠類IDCardFactory
IDCardFactory是工廠類Factory的具體實(shí)現(xiàn),通過createProduct方法生成具體的產(chǎn)品,并通過registerProduct方法將有owner生成的具體產(chǎn)品IDCard保存到owners實(shí)現(xiàn)產(chǎn)品注冊(cè)。
public class IDCardFactory extends Factory {
private List owners = new ArrayList();
protected Product createProduct(String owner) {
return new IDCard(owner);
}
protected void registerProduct(Product product) {
IDCard card = (IDCard)product;
owners.add(card.getOwner());
}
public List getOwners() {
return owners;
}
}
測試類Main
public class Main {
public static void main(String[] args) {
Factory factory = new IDCardFactory();
Product card1 = factory.create("小明");
Product card2 = factory.create("小紅");
Product card3 = factory.create("小剛");
card1.use();
card2.use();
card3.use();
}
}
輸出信息
制作ID卡小明
制作ID卡小紅
制作ID卡小剛
使用ID卡小明
使用ID卡小紅
使用ID卡小剛
在上面的介紹中我們的需求是生產(chǎn)一個(gè)IDCard,那么如果我們生成一個(gè)電視機(jī)呢,我們只需要?jiǎng)?chuàng)建一個(gè)電視機(jī)Televison和生成電視機(jī)的具體工廠類TelevisionFactory,在此,我們不需要修改產(chǎn)品類Product和工廠類Factory,就可以創(chuàng)建我們需要的產(chǎn)品。
抽象工廠模式
在上面的工廠方法中具體的產(chǎn)品和具體的工廠是一一對(duì)應(yīng)的,一個(gè)工廠只能生產(chǎn)一種產(chǎn)品,結(jié)構(gòu)單一,例如小米公司剛開始是只生產(chǎn)小米手機(jī),但是伴隨著公司的發(fā)展,他們需要生產(chǎn)不同型號(hào)的手機(jī),也會(huì)生產(chǎn)路由器,小米電視等等,那么工廠方法模式已不能滿足業(yè)務(wù)的需求了,此時(shí)我們就需要抽象工廠模式,即一個(gè)工廠可以生產(chǎn)多種產(chǎn)品。(當(dāng)然使用工廠方法也是可以的,不過需要?jiǎng)?chuàng)建多個(gè)具體工廠)
在抽象工廠模式中引入兩個(gè)重要的概念一個(gè)是產(chǎn)品等級(jí)結(jié)構(gòu),它是產(chǎn)品的繼承結(jié)構(gòu)例如一個(gè)抽象產(chǎn)品電視類它的子類可以為各種型號(hào)或的電視。那么產(chǎn)品族是什么呢?在上面提到小米可以生產(chǎn)手機(jī),電視,路由器等,那么這些就是一個(gè)產(chǎn)品族。
在圖解設(shè)計(jì)模式一書中,是通過將帶有層次結(jié)構(gòu)關(guān)系的集合標(biāo)簽制成HTML文件的示例講解抽象工廠模式的,不過我感覺示例代碼稍微有點(diǎn)多,所以基于自己的理解,通過開始所說的小米生產(chǎn)手機(jī)和電視的這個(gè)例子來總結(jié)抽象工廠模式。
照例先看類圖:
抽象產(chǎn)品
抽象產(chǎn)品角色負(fù)責(zé)定義抽象工廠生成的產(chǎn)品的接口,在本例中有兩個(gè)抽象產(chǎn)品類,分別是手機(jī)和電視的抽象類,對(duì)應(yīng)有一個(gè)打電話dial()和watchTV()方法
public abstract class IMobilePhone {
public abstract void dial();
}
public abstract class ITelevision {
public abstract void watchTV();
}
具體產(chǎn)品類
具體產(chǎn)品角色負(fù)責(zé)實(shí)現(xiàn)抽象產(chǎn)品角色的接口。
public class MobilePhone extends IMobilePhone {
private String name;
public MobilePhone(String name) {
this.name=name;
System.out.println("制作手機(jī)"+name);
}
@Override
public void dial() {
System.out.println("使用"+name+"打電話");
}
}
public class Television extends ITelevision {
private String name;
public Television(String name) {
this.name=name;
System.out.println("制作電視"+name);
}
@Override
public void watchTV() {
System.out.println("通過"+name+"看電視");
}
}
抽象工廠類
抽象工廠角色是負(fù)責(zé)定義用于生成抽象產(chǎn)品的接口。
public abstract class Factory {
public static Factory getFactory(String classname) {
Factory factory = null;
try {
factory = (Factory)Class.forName(classname).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("沒有找到 " + classname + "類。");
} catch (Exception e) {
e.printStackTrace();
}
return factory;
}
public abstract MobilePhone createMobilePhone(String type);
public abstract Television createTelevision(String type);
}
具體工廠
實(shí)現(xiàn)抽象工廠的抽象方法生成產(chǎn)品。
public class XiaoMiFactory extends Factory{
@Override
public MobilePhone createMobilePhone(String type) {
return new MobilePhone(type);
}
@Override
public Television createTelevision(String type) {
return new Television(type);
}
}
測試類
public class Main {
public static void main(String[] args) {
Factory factory = Factory.getFactory("com.abstractfactory.XiaoMiFactory");
IMobilePhone mobilePhone1=factory.createMobilePhone("小米2");
IMobilePhone mobilePhone2=factory.createMobilePhone("小米5");
ITelevision television1=factory.createTelevision("小米電視2");
ITelevision television2=factory.createTelevision("小米電視3");
mobilePhone1.dial();
mobilePhone2.dial();
television1.watchTV();
television2.watchTV();
}
}
輸出信息
制作手機(jī)小米2
制作手機(jī)小米5
制作電視小米電視2
制作電視小米電視3
使用小米2打電話
使用小米5打電話
通過小米電視2看電視
通過小米電視3看電視
兩者關(guān)系分析
對(duì)于工廠方法它是通過類繼承創(chuàng)建抽象產(chǎn)品,并且是創(chuàng)建一種產(chǎn)品,如果創(chuàng)建新的產(chǎn)品,只需新建一個(gè)工廠重載工廠方法以創(chuàng)建新的產(chǎn)品。
在抽象工廠模式中,它實(shí)現(xiàn)了具體類生成的分離,因此增加具體工廠變的很簡單,例如現(xiàn)在華為也生產(chǎn)手機(jī)和電視,我們只需要?jiǎng)?chuàng)建具體的工廠類就可以了。對(duì)于工廠類抽象工廠模式是很容易增加的,但是如果小米公司現(xiàn)在業(yè)務(wù)又拓展了,開始做機(jī)器人,這樣就困難了,我們需要將所有的工廠做修改,新增創(chuàng)建機(jī)器人的方法,如果之前工廠類很多,那么這個(gè)工作量就會(huì)很大了。
總而言之,這兩種都是工廠模式,形式上很相似,最終的目的都是為了解耦,實(shí)現(xiàn)低耦合。而且它們之間很容易互相轉(zhuǎn)換,當(dāng)我們使用工廠模式后可能加了一個(gè)方法就成為了抽象工廠模式。不管你如何使用,只有達(dá)到我們代碼低耦合,清晰明了的目的就可以。當(dāng)然這是個(gè)人感覺。
好了,自己關(guān)于工廠模式的理解到這里已經(jīng)總結(jié)完畢了。有問題歡迎留言指出,Have a wonderful day .
如需文章中所寫代碼,請(qǐng)移步GitHub查看