Javascript设计模式之工厂模式
设计模式并不是某一种语言所特有的,而是一种设计理念,现在学习Javascript的设计模式相关知识点。
工厂模式
工厂模式设计目标是:根据不同的需求创建实例化对象。我们将通过一个特定的需求来逐渐深入的讲解工程模式的用法。
我们需要达到的一个需求是,做一个音乐播放器,这个播放器有四个按钮,分别是上一首、下一首、播放暂停、静音。
针对上面的需求,我们先按照最简单的工厂模式写一个方法。
1 <script> 2 function WangyiMusicAction(action) { 3 var obj = new Object; 4 obj.vender = "网易云音乐"; 5 obj.playingMusic = "see you again"; 6 7 switch (action) { 8 case "last": 9 obj.information = { currentMusic: "小幸运", status: "200|404", message: "上一曲" }; 10 break; 11 case "next": 12 obj.information = { currentMusic: "野子", status: "200|404", message: "下一曲" }; 13 break; 14 case "play": 15 obj.information = { currentMusic: "see you again", status: "200|500", message: "播放" }; 16 break; 17 case "mute": 18 obj.information = { currentMusic: "see you again", status: "200|500", message: "静音" }; 19 break; 20 } 21 22 return obj; 23 }; 24 25 /***下面是调用测试代码***/ 26 var music = new WangyiMusicAction("next"); 27 console.log("音乐提供商:" + music.vender); // 网易云音乐 28 console.log("正在播放:" + music.playingMusic); // see you again 29 console.log("执行动作:" + music.information.message); // 下一曲 30 console.log("接口状态:" + music.information.status); // 200|404 31 console.log("执行动作后歌曲:" + music.information.currentMusic); //野子 32 33 </script>
通过给action传递不同的参数,可以获取不同的播放器状态。
面向对象理念
但是上述的方法并没有用到面向对象的理念,我们使用面向对象的思维重新修改上面的方法。
1 <script> 2 var WangyiMusicAction = function () { 3 this.vender = "网易云音乐"; 4 this.playingMusic = "see you again"; 5 }; 6 7 //扩展其prototype属性 8 WangyiMusicAction.prototype = { 9 last: function () { 10 this.information = { currentMusic: "小幸运", status: "200|404", message: "上一曲" }; 11 }, 12 next: function () { 13 this.information = { currentMusic: "野子", status: "200|404", message: "下一曲" }; 14 }, 15 play: function () { 16 this.information = { currentMusic: "see you again", status: "200|500", message: "播放" }; 17 }, 18 mute: function () { 19 this.information = { currentMusic: "see you again", status: "200|500", message: "静音" }; 20 } 21 }; 22 23 24 /***下面是调用测试代码***/ 25 var music = new WangyiMusicAction(); 26 console.log("音乐提供商:" + music.vender); // 网易云音乐 27 console.log("正在播放:" + music.playingMusic); // see you again 28 29 music.next(); // 执行下一曲动作 30 console.log("执行动作:" + music.information.message); // 下一曲 31 console.log("接口状态:" + music.information.status); // 200|404 32 console.log("执行动作后歌曲:" + music.information.currentMusic); //野子 33 34 </script>
在上述面向对象的工厂模式中,建立一个WangyiMusicAction对象,然后扩展其prototype属性,这样每个实例都会有自己的方法。
改进工厂模式
上面的工厂模式中,只能生成WangyiMusicAction的对象,如果我还要生成一个QQMusic和BaiduMusic,XiamiMusic,只有每个music都得写一遍方法,这是不值得推荐的。
我们可以通过一个Factory来动态创建各种类型的Music,首先是WangyiMusicAction。
优化工厂模式
但是在上面的工厂模式中,我们发现对于不同音乐提供商共用的属性可以封装成一个对象,用作父类继承。
1,定义父类
2,继承
通过修改prototype属性实现继承。
3,建立Factory工厂
建立工厂动态生成WangyiMusic或者QQMusic,然后生成一个QQMusic实例,并调用相应的方法。
1 <script> 2 //基类(父类)Music方法 3 var BaseMusic = function () { 4 this.playingMusic = "see you again"; 5 this.information = { 6 currentMusic: "", 7 status: "", 8 message: "" 9 }; 10 }; 11 12 //实现通用方法 13 BaseMusic.prototype = { 14 last: function () { 15 this.information.currentMusic = "小幸运"; 16 this.information.status = "200|404"; 17 this.information.message = "上一曲"; 18 }, 19 next: function () { 20 this.information.currentMusic = "野子"; 21 this.information.status = "200|404"; 22 this.information.message = "下一曲"; 23 }, 24 play: function () { 25 this.information.currentMusic = "see you again"; 26 this.information.status = "200|500"; 27 this.information.message = "播放"; 28 }, 29 mute: function () { 30 this.information.currentMusic = "see you again"; 31 this.information.status = "200|500"; 32 this.information.message = "静音"; 33 } 34 }; 35 36 37 //网易云音乐不同于父类的构造方法 38 var WangyiMusicAction = function (action) { 39 this.vender = "网易云音乐"; 40 }; 41 //通过prototype实现类继承 42 WangyiMusicAction.prototype = new BaseMusic(); //将动作放在基类,到达代码复用的目的 43 44 //QQ音乐不同于父类的构造方法 45 var QQMusicAction = function (action) { 46 this.vender = "QQ音乐"; 47 }; 48 //通过prototype实现类继承 49 QQMusicAction.prototype = new BaseMusic(); //将动作放在基类,到达代码复用的目的 50 51 52 //音乐工厂 53 var MusicFactory = function (type) { 54 switch (type) { 55 case "wangyi": 56 return new WangyiMusicAction(); 57 case "qq": 58 return new QQMusicAction(); 59 } 60 }; 61 62 /***下面是调用测试代码***/ 63 var music = new MusicFactory("wangyi"); 64 console.log("音乐提供商:" + music.vender); 65 console.log("正在播放:" + music.playingMusic); 66 67 music.next(); // 执行下一曲动作 68 console.log("执行动作:" + music.information.message); 69 console.log("接口状态:" + music.information.status); 70 console.log("执行动作后歌曲:" + music.information.currentMusic); 71 72 </script>
通过上述的继承父类方案,可以优化代码结构,工厂模式也使用的更加简洁。