博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JS设计模式之工厂模式
阅读量:4325 次
发布时间:2019-06-06

本文共 4974 字,大约阅读时间需要 16 分钟。

一般RPG游戏里, 一开始我们都要创建角色,选择职业,战士、法师还是弓箭手

var Character = function () {    },    Warrior = klass(Character),    Mage = klass(Character),    Archer = klass(Character),    Player = function () {    };    Character.prototype.level = function () {};Character.prototype.gather = function () {};Character.prototype.fight = function () {};Player.prototype.play = function (role) {    var character;    switch (role) {        case "战士":            character = new Warrior();            break;        case "法师":            character = new Mage();            break;        case "弓箭手":            character = new Archer();            break;        default:            character = new Warrior();    }    character.level();    character.gather();    character.fight();}; var player = new Player();player.play("法师");

Klass相当于extend的实现

var klass = (function () {    var F = function () {    };    return function (Parent) {        var Child;        Child = function () {            Child.superproto.constructor.apply(this, arguments);        };        F.prototype = Parent.prototype;        Child.prototype = new F();        Child.prototype.constructor = Child;        Child.superproto = Parent.prototype;        return Child;    };})();

这样写的问题在于,如果我们想要再加入一个新职业,比如盗贼,我们不得不找到Player,打开它的代码,给switch增加一个case,另外,如果还有PlayerVIP1,PlayerVIP2,PlayerVIP3...都在自己内部创建角色,那每一处都需要修改,也就是要修改客户端的代码,这听上去就让人觉得不太好,更好的办法是把创建角色的工作交给一个简单工厂来做。

这里值得一提的是,在教科书中显然会定义一个CharacterFactory类,但在JS里呢,是定义一个对象好还是一个构造函数好呢,我有点小纠结,感觉没有什么不同,书上说有时CharacterFactory类里直接定义静态方法,那么可能更接近对象一些,当然构造函数也是对象,给构造函数一个属性方法的话看起来是一样的。

简单工厂

var CharacterFactory = {    createCharacter: function (role) {        var character;        switch (role) {            case "战士":                character = new Warrior();                break;            case "法师":                character = new Mage();                break;            case "弓箭手":                character = new Archer();                break;            default:                character = new Warrior();        }        return character;    }};Player.prototype.play = function (role) {    var character = CharacterFactory.createCharacter(role);    character.level();    character.gather();    character.fight();};

现在只需要修改工厂对象就可以了,客户端代码保持不变Character.createCharacter(),也不是严格的不变,因为”战士“或”盗贼“的判断还是放在客户端,但是新增盗贼职业不还是要修改switch加一个case吗!这也违背了开闭原则。这时工厂方法(Factory Method)就登场了。

工厂方法

先定义一个工厂接口,这个接口定义了一个工厂方法来创建某一类型的产品,然后有任意数量的具体工厂来实现这个接口,在各自的工厂方法里创建那个类型产品的具体实例(TODO:这个优点我还没有太理解)。

var WarriorFactory = function() {},    MageFactory = function() {},    ArcherFactory = function() {};WarriorFactory.prototype.createCharacter = function() {    return new Warrior();};MageFactory.prototype.createCharacter = function() {    return new Mage();};ArcherFactory.prototype.createCharacter = function() {    return new Archer();};Player.prototype.play = function(role) {    var factory, character;    switch (role) {        case "战士":            factory = new WarriorFactory();            break;        case "法师":            factory = new MageFactory();            break;        case "弓箭手":            factory = new ArcherFactory();            break;        default :            factory = new WarriorFactory();    }    character = factory.createCharacter();    character.level();    character.gather();    character.fight();};

当我需要增加一个盗贼职业,就增加一个盗贼Factory,让它实现createCharacter方法,这样整个的工厂体系不会有修改的变化,而只是扩展的变化,符合了开闭原则。但是,修改的噩梦落到了客户端上,这是我的一个困惑,感觉没有简化,反而增加了一大堆类和方法,标记一个TODO。

当然,可以发挥JS灵活的特点

CharacterFactory = (function() {    var roles = {        Warrior: Warrior,        Mage: Mage,        Archer: Archer    };    return {        createCharacter: function(role) {            var Character = roles[role];            return Character ? new Character() : new Warrior();        },        registerCharacter: function(role, Character) {            var proto = Character.prototype;            if (proto.level && proto.gather && proto.fight) {                roles[role] = Character;            }        }    }})();Player.prototype.play = function(role) {    var character = CharacterFactory.createCharacter(role);    character.level();    character.gather();    character.fight();};var Assasin = klass(Character);CharacterFactory.registerCharacter("Assasin", Assasin);player.play("Assasin");

 

抽象工厂

让工厂方法模式里的工厂接口定义一系列的方法来创建一系列的产品,就成了抽象工厂

比如现在角色们需要武器,战士拿剑,法师拿法杖,这可不能弄错了

WarriorFactory.prototype.createCharacter = function() {    return new Warrior();};WarriorFactory.prototype.createWeapon = function() {    return new Sword();};MageFactory.prototype.createCharacter = function() {    return new Mage();};MageFactory.prototype.createWeapon = function() {    return new Wand();};ArcherFactory.prototype.createCharacter = function() {    return new Archer();};ArcherFactory.prototype.createWeapon = function() {    return new Bow();};var factory = new WarriorFactory(),    character = factory.createCharacter(),    weapon = factory.createWeapon();

我目前对JS应用工厂模式的一些理解,还没有理解透彻,不足之处,请指正:)

转载于:https://www.cnblogs.com/coiorz/p/4806550.html

你可能感兴趣的文章
别人抢红包,我们研究一下红包算法
查看>>
泛型的一些问题
查看>>
PHP与正则表达式 2 :一些修饰符与preg_match_all
查看>>
压八位高精度 高精操作大全
查看>>
进程、线程、协程和GIL(二)
查看>>
dockerfile语法规则
查看>>
模块的导入
查看>>
《Inside C#》笔记(八) 接口
查看>>
kafka介绍
查看>>
java类加载机制及方法调用
查看>>
《大话西游》:我的意中人是一个盖世英雄
查看>>
iOS 清除xcode缓存和生成文件
查看>>
为什么幻灯片画布不居中
查看>>
flask模板应用-javaScript和CSS中jinja2 --
查看>>
react-native 调用原生方法
查看>>
查看Mac系统所有USB设备信息 解决android studio无法识别真机问题
查看>>
20145238 《信息安全系统设计基础》第2周学习总结
查看>>
android 获取日期
查看>>
HDU-1018 BigNumber(斯特林近似)
查看>>
Excel公式——单元格前加固定字符串
查看>>