通過(guò)一的文章弛姜,我們知道簡(jiǎn)單工廠是不符合開(kāi)閉原則的,而工廠模式剛好可以解決此缺陷妖枚。
定義
定義一個(gè)創(chuàng)建對(duì)象的接口廷臼,但讓實(shí)現(xiàn)這個(gè)接口的類來(lái)決定實(shí)例化哪個(gè)類
工廠方法讓類的實(shí)例化推遲到子類中進(jìn)行
適用場(chǎng)景
- 創(chuàng)建對(duì)象需要大量的重復(fù)代碼
- 客戶端不依賴與產(chǎn)品實(shí)例如何被創(chuàng)建、實(shí)現(xiàn)等細(xì)節(jié)
- 一個(gè)類通過(guò)其子類來(lái)指定創(chuàng)建哪個(gè)對(duì)象
代碼示例
同樣是上一節(jié)的生產(chǎn)Cpu的業(yè)務(wù)場(chǎng)景绝页,這次我們用工廠模式來(lái)進(jìn)行創(chuàng)建
- 產(chǎn)品類的定義
public interface Cpu
{
void produce();
}
public class KirinCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("華為麒麟處理器");
}
}
public class MtkCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("聯(lián)發(fā)科處理器");
}
}
public class SnapdragonCpu implements Cpu
{
@Override
public void produce()
{
System.out.println("高通驍龍?zhí)幚砥?);
}
}
在這里我們創(chuàng)建一個(gè)Cpu產(chǎn)品的接口荠商,并定義了它的三個(gè)實(shí)現(xiàn)類
- 接下來(lái)我們定義工廠類的接口和實(shí)現(xiàn)
首先定義生產(chǎn)Cpu的工廠,這里應(yīng)該定義為抽象類或接口续誉,而具體的實(shí)現(xiàn)交給工廠實(shí)現(xiàn)類
public abstract class CpuFactory
{
public abstract Cpu getCpu();
}
我們同樣定義三個(gè)工廠實(shí)現(xiàn)類
public class KirinCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new KirinCpu();
}
}
public class MtkCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new MtkCpu();
}
}
public class SnapdragonCpuFactory extends CpuFactory
{
@Override
public Cpu getCpu()
{
return new SnapdragonCpu();
}
}
- 在客戶類中我們就可以直接調(diào)用某個(gè)產(chǎn)品對(duì)應(yīng)的工廠類來(lái)生產(chǎn)該產(chǎn)品
public class Client
{
public static void main(String[] args)
{
CpuFactory cpuFactory1 = new MtkCpuFactory();
CpuFactory cpuFactory2 = new SnapdragonCpuFactory();
CpuFactory cpuFactory3 = new KirinCpuFactory();
Cpu cpu1 = cpuFactory1.getCpu();
Cpu cpu2 = cpuFactory2.getCpu();
Cpu cpu3 = cpuFactory3.getCpu();
cpu1.produce();
cpu2.produce();
cpu3.produce();
}
}
其UML類圖如下
擴(kuò)展性
工廠模式解決了簡(jiǎn)單工廠模式的擴(kuò)展性問(wèn)題莱没,當(dāng)要添加新的產(chǎn)品的時(shí)候,我們只需要新建一個(gè)該產(chǎn)品對(duì)應(yīng)的工廠類酷鸦。
缺點(diǎn)
工廠模式雖然符合開(kāi)閉原則饰躲,但是它本身也帶來(lái)了一些新的問(wèn)題
- 類的個(gè)數(shù)過(guò)多,容易增加復(fù)雜度
- 增加了系統(tǒng)的抽象性和理解難度
應(yīng)用
Collection類的iterator()方法
Collection應(yīng)該是我們?cè)趈ava里非常熟悉的接口了臼隔,我們常用的許多各種數(shù)據(jù)結(jié)構(gòu)都是該接口的實(shí)現(xiàn)属铁。而iterator()方法的聲明如下
Iterator<E> iterator();
其返回的Iteartor對(duì)象是一個(gè)接口
java中的ArrayList是Collection接口的實(shí)現(xiàn),而其也必定實(shí)現(xiàn)了該工廠方法躬翁。它的具體實(shí)現(xiàn)代碼如下
public Iterator<E> iterator() {
return new Itr();
}
該方法返回了一個(gè)ArrayList的Iterator的實(shí)現(xiàn)焦蘑,其定義在ArrayList內(nèi)部,是一個(gè)內(nèi)部類盒发,類的聲明如下
private class Itr implements Iterator<E>
同樣我們也可以在LinkedList找到其對(duì)應(yīng)的實(shí)現(xiàn)類以及實(shí)現(xiàn)方法例嘱,在此就不展示了
slf4j中的ILoggerFactory
我們?cè)谟胹lf4j獲取日志時(shí)經(jīng)常會(huì)調(diào)用以下方法來(lái)獲取日志
Logger logger = LoggerFactory.getLogger(getClass());
其內(nèi)部實(shí)現(xiàn)如下
而ILoggerFactory是一個(gè)接口,代表生成logger對(duì)象的工廠宁舰,注意Logger也是一個(gè)接口
其定義如下
public interface ILoggerFactory {
public Logger getLogger(String name);
}
它有以下實(shí)現(xiàn)類
在這里L(fēng)ogger相當(dāng)于Cpu拼卵,ILoggerFactory相當(dāng)于CpuFactory,而我們獲得的Logger對(duì)象是由對(duì)應(yīng)的ILoggerFactory的實(shí)現(xiàn)生成的