看看用TypeScript怎樣實現常見的設計模式,順便複習一下。
學模式最重要的不是記UML,而是知道什麼模式能夠解決什麼樣的問題,在作項目時碰到問題能夠想到用哪一個模式能夠解決,UML忘了能夠查,思想記住就好。
這裏儘可能用原創的,實際中能碰到的例子來講明模式的特色和用處。設計模式
下面用TypeScript寫一個槍工廠來看看簡單工廠模式:架構
enum GunType{ AK, M4A1, } interface Shootable{ shoot(); } abstract class Gun implements Shootable{ // 抽象產品 - 槍 abstract shoot(); } class AK47 extends Gun{ //具體產品 - AK47 shoot(){ console.log('ak47 shoot.'); } } class M4A1 extends Gun{ //具體產品 - M4A1 shoot(){ console.log('m4a1 shoot.'); } } class GunFactory{ static createGun(type: GunType): Gun{ switch(type){ case GunType.AK: return new AK47(); case GunType.M4A1: return new M4A1(); default: throw Error('not support this gun yet'); } } } GunFactory.createGun(GunType.AK).shoot(); GunFactory.createGun(GunType.M4A1).shoot(); //輸出 ak47 shoot. m4a1 shoot.
上面代碼GunFactory
工廠就是根據類型來建立不一樣的產品,使用的時候只須要引入這個工廠和接口便可。
這樣就把變化封裝到了工廠中,若是之後要支持狙擊槍,只須要加個實現Gun
接口的Sniper
類就能夠了。app
繼續用TypeScript寫一個槍工廠來看看工廠方法模式:框架
interface Shootable{ shoot(); } abstract class Gun implements Shootable{ // 抽象產品 - 槍 abstract shoot(); } class AK47 extends Gun{ //具體產品 - AK47 shoot(){ console.log('ak47 shoot.'); } } class M4A1 extends Gun{ //具體產品 - M4A1 shoot(){ console.log('m4a1 shoot.'); } } abstract class GunFactory{ //抽象槍工廠 abstract create(): Gun; } class AK47Factory extends GunFactory{ //Ak47工廠 create(): Gun{ let gun = new AK47(); // 生產Ak47 console.log('produce ak47 gun.'); this.clean(gun); // 清理工做 this.applyTungOil(gun);// Ak47是木頭槍托,塗上桐油 return gun; } private clean(gun: Gun){ //清洗 console.log('clean gun.'); } private applyTungOil(gun: Gun){ //塗上桐油 console.log('apply tung oil.'); } } class M4A1Factory extends GunFactory{ //M4A1工廠 create(): Gun{ let gun = new M4A1(); // 生產M4A1 console.log('produce m4a1 gun.'); this.clean(gun); // 清理工做 this.sprayPaint(gun); // M4是全金屬,噴上漆 return gun; } private clean(gun: Gun){ //清洗 console.log('clean gun.'); } private sprayPaint(gun: Gun){ //噴漆 console.log('spray paint.'); } } let ak47 = new AK47Factory().create(); ak47.shoot(); let m4a1 = new M4A1Factory().create(); m4a1.shoot(); //output produce ak47 gun. clean gun. apply tung oil. ak47 shoot. produce m4a1 gun. clean gun. spray paint. m4a1 shoot.
能夠看到Ak47和M4A1在生產出來後的處理不同,Ak須要塗桐油,M4須要噴漆,用簡單工廠就比較難作到,因此就每一個產品都弄個工廠來封裝各本身的生產過程。
另外的好處是當加入其餘槍好比沙漠之鷹時,再加一個產品和產品工廠就行了,並不須要改變現有代碼,算是作到了遵照開閉原則。
缺點也明顯,增長一個產品就須要多加兩個類,增長了代碼複雜性。this
繼續用槍,外加子彈,用TypeScript寫一個抽象槍工廠來看看抽象工廠模式:設計
interface Shootable{ shoot(); } abstract class Gun implements Shootable{ // 抽象產品 - 槍 private _bullet: Bullet; addBullet(bullet: Bullet){ this._bullet = bullet; } abstract shoot(); } class AK47 extends Gun{ //具體產品 - AK47 shoot(){ console.log(`ak47 shoot with ${this._bullet}.`); } } class M4A1 extends Gun{ //具體產品 - M4A1 shoot(){ console.log(`m4a1 shoot with ${this._bullet}.`); } } abstract class Bullet{ // 抽象子彈 abstract name: string; } class AkBullet{ // AK 子彈 name: string = 'ak bullet'; } class M4Bullet{ // m4a1 子彈 name: string = 'm4a1 bullet'; } abstract class ArmFactory{ //抽象軍工廠 abstract createGun(): Gun; abstract createBullet(): Bullet; } class AK47Factory extends ArmFactory{ createGun(): Gun{ let gun = new AK47(); // 生產Ak47 console.log('produce ak47 gun.'); this.clean(gun); // 清理工做 this.applyTungOil(gun);// Ak47是木頭槍托,塗上桐油 return gun; } private clean(gun: Gun){ //清洗 console.log('clean gun.'); } private applyTungOil(gun: Gun){ //塗上桐油 console.log('apply tung oil.'); } createBullet(): Bullet{ return new AkBullet(); } } class M4A1Factory extends ArmFactory{ //M4A1工廠 createGun(): Gun{ let gun = new M4A1(); // 生產M4A1 console.log('produce m4a1 gun.'); this.clean(gun); // 清理工做 this.sprayPaint(gun); // M4是全金屬,噴上漆 return gun; } private clean(gun: Gun){ //清洗 console.log('clean gun.'); } private sprayPaint(gun: Gun){ //噴漆 console.log('spray paint.'); } createBullet(): Bullet{ return new M4Bullet(); } } //使用 function shoot(gun: Gun, bullet: Bullet) // 使用生產的槍和子彈 { gun.addBullet(bullet); gun.shoot(); } let akFactory = new AK47Factory(); shoot(akFactory.createGun(), akFactory.createBullet()); let m4a1Factory = new M4A1Factory(); shoot(m4a1Factory.createGun(), m4a1Factory.createBullet()); //輸出 produce ak47 gun. clean gun. apply tung oil. add bullet: ak bullet ak47 shoot with ak bullet. produce m4a1 gun. clean gun. spray paint. add bullet: m4a1 bullet m4a1 shoot with m4a1 bullet.
工廠除了生產槍外還生產子彈,子彈和槍算是一個產品族,使用者接觸到的只有抽象工廠和抽象產品,隱藏了具體實現細節。
在大的框架下面有不少小項目時用抽象工廠配合如動態對象生成之類的技術就能夠很容易實現靈活的架構。code