外貿(mào)網(wǎng)站推廣計(jì)劃關(guān)鍵詞排名工具
說明:本文介紹設(shè)計(jì)模式中,創(chuàng)建型設(shè)計(jì)模式中的工廠模式;
飛機(jī)大戰(zhàn)
創(chuàng)建型設(shè)計(jì)模式,關(guān)注于對(duì)象的創(chuàng)建,本文介紹的簡(jiǎn)單工廠和工廠模式同樣也是。舉一個(gè)游戲例子,如飛機(jī)大戰(zhàn)游戲中,屏幕中敵人類型有坦克、飛機(jī),會(huì)隨機(jī)出現(xiàn)在畫面的上方;
我們可以簡(jiǎn)單的將敵人抽象為一個(gè)抽象類,然后分別創(chuàng)建對(duì)應(yīng)的實(shí)現(xiàn)類,如下:
(敵人抽象類,注意屬性的修飾符,protected,子類中需要用到)
/*** 敵人抽象類*/
public abstract class Enemy {/*** 敵人的坐標(biāo)*/protected int x;/*** 敵人的坐標(biāo)*/protected int y;/*** 抽象方法*/public Enemy(int x, int y) {this.x = x;this.y = y;}/*** 繪制方法*/public abstract void show();
}
(具體實(shí)現(xiàn)類,坦克)
/*** 坦克*/
public class Tank extends Enemy{public Tank(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("坦克出現(xiàn)了,坐標(biāo)是:" + x + "," + y);}
}
(具體實(shí)現(xiàn)類,飛機(jī))
/*** 飛機(jī)*/
public class AirPlane extends Enemy{public AirPlane(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("飛機(jī)出現(xiàn)了,坐標(biāo)是:" + x + "," + y);}
}
(客戶端,client)
import java.util.Random;/*** 客戶端*/
public class Client {public static void main(String[] args) {// 屏幕寬度是100int screenLength = 100;// 創(chuàng)建坦克Enemy tank = new Tank(new Random().nextInt(screenLength),0);tank.show();// 創(chuàng)建飛機(jī)Enemy airPlane = new AirPlane(new Random().nextInt(screenLength),0);airPlane.show();}
}
執(zhí)行結(jié)果:
分析:以上創(chuàng)建方式,有兩點(diǎn)不足之處,對(duì)象的創(chuàng)建和使用在一起,耦合性太高;創(chuàng)建對(duì)象的代碼放到了客戶端類里,如果需要?jiǎng)?chuàng)建多個(gè)對(duì)象的話,客戶端的代碼勢(shì)必會(huì)越來越臃腫。
簡(jiǎn)單工廠
為了解決上面提到的兩個(gè)問題,耦合性高,客戶端代碼臃腫,我們可以使用簡(jiǎn)單工廠對(duì)上面的流程進(jìn)行改進(jìn)。如下,創(chuàng)建一個(gè)簡(jiǎn)單工廠類,將創(chuàng)建對(duì)象的步驟抽取到這里面:
import java.util.Random;/*** 簡(jiǎn)單工廠*/
public class SimpleFactory {/*** 屏幕寬度*/private int screenLength;/*** 隨機(jī)數(shù)*/private Random random;/*** 構(gòu)造函數(shù)** @param screenLength*/public SimpleFactory(int screenLength) {this.screenLength = screenLength;this.random = new Random();}/*** 創(chuàng)建敵人* @param type* @return*/public Enemy createEnemy(String type) {int x = random.nextInt(screenLength);Enemy enemy = null;switch (type) {case "Tank":enemy = new Tank(x, 0);break;case "AirPlane":enemy = new AirPlane(x, 0);break;default:throw new RuntimeException("unknown enemy type");}return enemy;}
}
這樣,客戶端就可以使用這個(gè)簡(jiǎn)單工廠來創(chuàng)建對(duì)象了,如下:
/*** 客戶端*/
public class Client {public static void main(String[] args) {int screenLength = 100;new SimpleFactory(screenLength).createEnemy("Tank").show();new SimpleFactory(screenLength).createEnemy("AirPlane").show();}
}
執(zhí)行結(jié)果:
分析:通過簡(jiǎn)單工廠,對(duì)對(duì)象的創(chuàng)建進(jìn)行了封裝,使客戶端的代碼簡(jiǎn)單、清爽。但是,如果需要增加敵人類型的話,我們就需要去修改這個(gè)簡(jiǎn)單工廠類,新增case分支,這不利于后續(xù)的代碼擴(kuò)展。
工廠模式
使用工廠模式,可以彌補(bǔ)簡(jiǎn)單工廠的缺點(diǎn)。我們可以創(chuàng)建一個(gè)工廠接口,讓后續(xù)所有的敵人對(duì)象都實(shí)現(xiàn)這個(gè)接口,并實(shí)現(xiàn)其抽象方法,把對(duì)象的創(chuàng)建放到具體實(shí)現(xiàn)類中,這樣后續(xù)無論新增多少種敵人類型,都只要實(shí)現(xiàn)這個(gè)接口即可,不需要對(duì)原有系統(tǒng)進(jìn)行修改。如下:
(工廠接口)
/*** 敵人工廠接口*/
public interface Factory {/*** 創(chuàng)建敵人* * @param screenLength* @return*/Enemy createEnemy(int screenLength);
}
(飛機(jī)工廠)
import java.util.Random;/*** 飛機(jī)工廠*/
public class AirPlaneFactory implements Factory{@Overridepublic Enemy createEnemy(int screenLength) {return new AirPlane(new Random().nextInt(screenLength), 0);}
}
(坦克工廠)
import java.util.Random;/*** 坦克工廠*/
public class TankFactory implements Factory{@Overridepublic Enemy createEnemy(int screenLength) {return new Tank(new Random().nextInt(screenLength), 0);}
}
現(xiàn)在,如果需要新增一個(gè)Boss對(duì)象,只需要?jiǎng)?chuàng)建對(duì)應(yīng)的Boss對(duì)象,及其工廠實(shí)現(xiàn)類即可,如下:
(Boss類)
/*** Boss*/
public class Boss extends Enemy{public Boss(int x, int y) {super(x, y);}@Overridepublic void show() {System.out.println("Boss出現(xiàn)了,坐標(biāo)是:" + x + "," + y);}
}
(Boss工廠實(shí)現(xiàn)類,用于創(chuàng)建Boss)
import java.util.Random;/*** Boss工廠*/
public class BossFactory implements Factory {@Overridepublic Enemy createEnemy(int screenLength) {// Boss出現(xiàn)在屏幕正中間return new Boss(new Random().nextInt(screenLength) / 2, 0);}
}
(客戶端代碼,客戶端只需創(chuàng)建工廠對(duì)象,調(diào)用其方法即可)
/*** 客戶端*/
public class Client {public static void main(String[] args) {// 屏幕寬度int screenLength = 100;// 創(chuàng)建坦克Factory tankFactory = new TankFactory();for (int i = 0; i < 10; i++) {tankFactory.createEnemy(screenLength).show();}// 創(chuàng)建飛機(jī)Factory airFactory = new AirPlaneFactory();for (int i = 0; i < 10; i++) {airFactory.createEnemy(screenLength).show();}// 創(chuàng)建BossFactory boosFactory = new BossFactory();boosFactory.createEnemy(screenLength).show();}
}
執(zhí)行結(jié)果:
總結(jié)
本文參考《設(shè)計(jì)模式的藝術(shù)》、《秒懂設(shè)計(jì)模式》兩書