定義
簡(jiǎn)單工廠也有稱靜態(tài)工廠,其定義一個(gè)工廠類,根據(jù)傳入的不同參數(shù)返回不同的實(shí)例,被創(chuàng)建的對(duì)象實(shí)例具有共同的父類或接口。其本質(zhì)是只需一個(gè)工廠類,便可創(chuàng)建若干個(gè)不同的產(chǎn)品類型。
使用場(chǎng)景
- 需要?jiǎng)?chuàng)建的對(duì)象較少,且對(duì)象具有相同的性質(zhì),如共同父類或都實(shí)現(xiàn)了某接口;
- 創(chuàng)建的過程不需要客戶端關(guān)心
UML類圖
代碼示例
創(chuàng)建一個(gè)可以繪制不同形狀的繪圖工具,可以繪制多種圖形如圓形、三角形、矩形等。代碼可如下:
/**
* 定義抽象產(chǎn)品類
* <p>可定義為抽象類或者接口,但是接口更方便擴(kuò)展,且可以多繼承實(shí)現(xiàn)</>
*/
interface Shape {
void draw();
}
/**
* 具體實(shí)現(xiàn)產(chǎn)品類1
*/
class Circle implements Shape {
public Circle() {
System.out.println("Circle created");
}
@Override
public void draw() {
System.out.println("draw a circle");
}
}
/**
* 具體實(shí)現(xiàn)產(chǎn)品類2
*/
class Triangle implements Shape {
public Triangle() {
System.out.println("Triangle created");
}
@Override
public void draw() {
System.out.println("draw a triangle");
}
}
/**
* 具體實(shí)現(xiàn)產(chǎn)品類3
*/
class Rect implements Shape {
public Rect() {
System.out.println("Rect created");
}
@Override
public void draw() {
System.out.println("draw a rect");
}
}
/**
* 產(chǎn)品類型枚舉
*/
enum ShapeType {
CIRCLE,
TRIANGLE,
RECT
}
/**
* 簡(jiǎn)單工廠/靜態(tài)工廠
*/
class ShapeFactory {
public static Shape getShape(ShapeType type) {
switch (type) {
case CIRCLE:
return new Circle();
case TRIANGLE:
return new Triangle();
case RECT:
return new Rect();
}
return new Circle();
}
}
public class SimpleFactoryTest {
public static void main(String[] args) {
Shape shape = ShapeFactory.getShape(ShapeType.CIRCLE);
shape.draw();
shape = ShapeFactory.getShape(ShapeType.TRIANGLE);
shape.draw();
shape = ShapeFactory.getShape(ShapeType.RECT);
shape.draw();
}
}
最終輸出結(jié)果如下:
Circle created
draw a circle
Triangle created
draw a triangle
Rect created
draw a rect
二、工廠方法模式
定義
定義一個(gè)用于創(chuàng)建對(duì)象的接口,讓子類決定具體創(chuàng)建去實(shí)例化哪個(gè)類,將類的實(shí)例化延遲到其子類。 與簡(jiǎn)單工廠最大的不同在于,簡(jiǎn)單工廠只需要一個(gè)統(tǒng)一的工廠類便可完成所有產(chǎn)品對(duì)象的創(chuàng)建,而工廠方法模式則需要為每個(gè)產(chǎn)品類型定義一個(gè)工廠類,由具體的工廠類去創(chuàng)建具體的產(chǎn)品。
UML類圖
代碼示例 現(xiàn)在需要設(shè)計(jì)一個(gè)這樣的圖片加載類,它具有多個(gè)圖片加載器,用來加載jpg,png,gif格式的圖片,每個(gè)加載器都有一個(gè)read()方法,用于讀取圖片。下面我們完成這個(gè)圖片加載類。
/**
* 首先完成圖片加載其的設(shè)計(jì),編寫一個(gè)加載的公共接口
*/
interface Reader {
void read();
}
/**
* jpg圖片加載器
*/
class JpgReader implements Reader {
@Override
public void read() {
System.out.println("read jpg");
}
}
/**
* png加載器
*/
class PngReader implements Reader {
@Override
public void read() {
System.out.println("read png");
}
}
/**
* gif加載器
*/
class GifReader implements Reader {
@Override
public void read() {
System.out.println("read gif");
}
}
/**
* 定義一個(gè)抽象的工廠類
*/
interface ReaderFactory {
Reader getReader();
}
/**
* jpg加載器工廠
*/
class JpgReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new JpgReader();
}
}
/**
* png加載器工廠
*/
class PngReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new PngReader();
}
}
/**
* gif加載器工廠
*/
class GifReaderFactory implements ReaderFactory {
@Override
public Reader getReader() {
return new GifReader();
}
}
public class FactoryTest {
public static void main(String[] args) {
ReaderFactory factory = new JpgReaderFactory();
Reader reader = factory.getReader();
reader.read();
factory = new PngReaderFactory();
reader = factory.getReader();
reader.read();
factory = new GifReaderFactory();
reader = factory.getReader();
reader.read();
}
}
輸出結(jié)果:
read jpg
read png
read gif
適用場(chǎng)景
- 客戶端不需要知道它所創(chuàng)建的對(duì)象的類。例子中我們不知道每個(gè)圖片加載器具體叫什么名,只知道創(chuàng)建它的工廠名就完成了創(chuàng)建過程;
- 客戶端可以通過子類來指定創(chuàng)建對(duì)應(yīng)的對(duì)象。
三、抽象工廠模式
定義
提供一個(gè)創(chuàng)建一組相關(guān)或者相互依賴對(duì)象的接口,而不需要指定它們的具體類。每一個(gè)具體工廠都提供了多個(gè)工廠方法用于產(chǎn)生多種不同類型的對(duì)象。
抽象工廠和工廠方法一樣可以劃分為4大部分:
-
AbstractFactory
(抽象工廠)聲明了一組用于創(chuàng)建對(duì)象的方法,注意是一組; -
ConcreteFactory
(具體工廠):它實(shí)現(xiàn)了在抽象工廠中聲明的創(chuàng)建對(duì)象的方法,生成一組具體對(duì)象; -
AbstractProduct
(抽象產(chǎn)品):它為每種對(duì)象聲明接口,在其中聲明了對(duì)象所具有的業(yè)務(wù)方法; -
ConcreteProduct
(具體產(chǎn)品):它定義具體工廠生產(chǎn)的具體對(duì)象。
UML類圖
代碼示例
現(xiàn)在需要做一款跨平臺(tái)的游戲,需要兼容Android,Ios,Wp三個(gè)移動(dòng)操作系統(tǒng),該游戲針對(duì)每個(gè)系統(tǒng)都設(shè)計(jì)了一套操作控制器(OperationController)和界面控制器(UIController),下面通過抽閑工廠方式完成這款游戲的架構(gòu)設(shè)計(jì)。
由題可知,游戲里邊的各個(gè)平臺(tái)的UIController和OperationController應(yīng)該是我們最終生產(chǎn)的具體產(chǎn)品。所以新建兩個(gè)抽象產(chǎn)品接口。
抽象操作控制器
public interface OperationController {
void control();
}
抽象界面控制器
public interface UIController {
void display();
}
然后完成各個(gè)系統(tǒng)平臺(tái)的具體操作控制器和界面控制器
Android
public class AndroidOperationController implements OperationController {
@Override
public void control() {
System.out.println("AndroidOperationController");
}
}
public class AndroidUIController implements UIController {
@Override
public void display() {
System.out.println("AndroidInterfaceController");
}
}
iOS
public class IosOperationController implements OperationController {
@Override
public void control() {
System.out.println("IosOperationController");
}
}
public class IosUIController implements UIController {
@Override
public void display() {
System.out.println("IosInterfaceController");
}
}
WP
public class WpOperationController implements OperationController {
@Override
public void control() {
System.out.println("WpOperationController");
}
}
public class WpUIController implements UIController {
@Override
public void display() {
System.out.println("WpInterfaceController");
}
}
下面定義一個(gè)抽閑工廠,該工廠需要可以創(chuàng)建OperationController和UIController
public interface SystemFactory {
public OperationController createOperationController();
public UIController createInterfaceController();
}
在各平臺(tái)具體的工廠類中完成操作控制器和界面控制器的創(chuàng)建過程
Android
public class AndroidFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new AndroidOperationController();
}
@Override
public UIController createInterfaceController() {
return new AndroidUIController();
}
}
iOS
public class IosFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new IosOperationController();
}
@Override
public UIController createInterfaceController() {
return new IosUIController();
}
}
WP
public class WpFactory implements SystemFactory {
@Override
public OperationController createOperationController() {
return new WpOperationController();
}
@Override
public UIController createInterfaceController() {
return new WpUIController();
}
}
具體使用
public class Test{
public static void main() {
SystemFactory mFactory;
UIController interfaceController;
OperationController operationController;
// Android
mFactory=new AndroidFactory();
// iOS
mFactory=new IosFactory();
// Wp
mFactory=new WpFactory();
interfaceController=mFactory.createInterfaceController();
operationController=mFactory.createOperationController();
interfaceController.display();
operationController.control();
}
}
針對(duì)不同平臺(tái)只通過創(chuàng)建不同的工廠對(duì)象就完成了操作和UI控制器的創(chuàng)建。小伙伴們可以對(duì)比一下,如果這個(gè)游戲使用工廠方法模式搭建需要?jiǎng)?chuàng)建多少個(gè)工廠類呢?下面總結(jié)一下抽象工廠的適用場(chǎng)景。
適用場(chǎng)景:
- 和工廠方法一樣客戶端不需要知道它所創(chuàng)建的對(duì)象的類。
- 需要一組對(duì)象共同完成某種功能時(shí)。并且可能存在多組對(duì)象完成不同功能的情況。
- 系統(tǒng)結(jié)構(gòu)穩(wěn)定,不會(huì)頻繁的增加對(duì)象。(因?yàn)橐坏┰黾泳托枰薷脑写a,不符合開閉原則)