看看用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类就可以了。
继续用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需要喷漆,用简单工厂就比较难做到,所以就每个产品都弄个工厂来封装各自己的生产过程。
另外的好处是当加入其他枪比如沙漠之鹰时,再加一个产品和产品工厂就好了,并不需要改变现有代码,算是做到了遵守开闭原则。
缺点也明显,增加一个产品就需要多加两个类,增加了代码复杂性。