看看用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