博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式-工厂方法模式<二>
阅读量:5323 次
发布时间:2019-06-14

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

前面的理论先不管了,直接解析代码。

计算器程序的UML类图

 

代码解析

在讲解模式之前,先介绍两个辅助函数/对象

View Code
/** * 用于创建接口的类,并带有检查功能 */var Interface = function(name, methods) {    //检查参数个数    if(arguments.length != 2) {        //错误显示不能准确定位        throw new Error('创建接口的对象需要2个参数:接口名,其方法名组成的数组');    }    //确保第二个参数是数组类型    if(!(methods instanceof Array)) {        throw new Error('创建接口的第二参数应为数组类型');    }    //为接口创建两个属性,并赋值    this.name = name;    this.methods = [];              //存储接口方法    for(var i=0; methods[i]; i++) {        if(typeof methods[i] !== 'string') {            throw new Error('接口的方法名应为字符串');        }        this.methods.push(methods[i]);    }};/** * 检查创建的实例是否存在接口中的所有方法 * 使用方法:把此函数紧跟创建实例语句后面 * @param {Object} object 实例 * @param {multi} interfaces 接口列表 */Interface.ensureImplement = function(object, interfaces) {    //检查参数个数    if(arguments.length < 2) throw new Error('接口类的静态ensureImplement方法参数不能少于2个');    //子类实现的接口    var intface = null;    //检查子类是否实现了接口所有方法    for(var i=1; arguments[i]; i++) {        intface = arguments[i];        //判断传递的参数是否都是合法的接口实例        if(intface.constructor !== Interface) throw new Error('用ensureImplement检查时,发现'+intface+'不是合法的接口');        //获取接口的所有方法        var methods = intface.methods;        //检查子类是否实现了接口中的所有方法        for(var j=0; methods[j]; j++) {            var method = methods[j];            if(!object[method] || typeof object[method]!='function') {                throw new Error('没有实现'+intface.name+'接口的方法:'+method);            }        }    }};

 创建接口的示例:

//创建运算类接口var Operation = new Interface('Operation', ['getResult']);//-----------------------------------------------------//...IFactory.prototype.getResult = function(a, b) {    var oper = this.factoryMethod();    //判断实例是否实现了Operation接口中的所有方法    Interface.ensureImplement(oper, Operation);    return oper.getResult(a, b);};

下面是辅助函数extend()用于继承操作

View Code
/** * 实现原型对象继承 */var extend = function(subClass, superClass) {    var F = function() {};    F.prototype = superClass.prototype;    subClass.prototype = new F();    subClass.prototype.constructor = subClass;        subClass.superclass = superClass.prototype;    if(superClass.prototype.constructor === Object.prototype.constructor) {        superClass.prototype.constructor = superClass;    }};

 工厂方法模式实现计算器程序中所有的类统计:

/* * 工厂方法 * IFactory * AddFactory * SubFactory * MulFactory * DivFactory *  * Operation * OperationAdd * OperationSub * OperationMul * OperationDiv */

 创建运算类接口,并用各个运算符实现具体类。其中用到了接口。

//创建运算类接口var Operation = new Interface('Operation', ['getResult']);//具体的实现接口的加法运算类var OperationAdd = function() {};           //implements OperationOperationAdd.prototype.getResult = function(a, b) {    return a+b;};//减法运算类var OperationSub = function() {};           //implements OperationOperationSub.prototype.getResult = function(a, b) {    return a-b;};//...

 继承可以有类式继承和原型式继承,本程序实现了这两种方法

类式继承实现工厂方法的继承

View Code
/*  * 抽象类 * 创建器,声明工厂方法  */var IFactory = function() {};/** * 1. 获取具体运算类实例,并检查是否实现了接口 * 2. 用获取的实例调用同名运算方法 * @param {Number} a * @param {Number} b * @return {Number} */IFactory.prototype.getResult = function(a, b) {    var oper = this.factoryMethod();    //判断实例是否实现了Operation接口中的所有方法    Interface.ensureImplement(oper, Operation);    return oper.getResult(a, b);};IFactory.prototype.factoryMethod = function() {    throw new Error('IFactory是一个抽象类,子类需要实现factoryMethod方法');};/* * 加法工厂类 * 具体的创建器,实现IFactory中的工厂方法,并返回具体的运算符对象 */var AddFactory = function() {};//继承IFactory抽象类extend(AddFactory, IFactory);           AddFactory.prototype.factoryMethod = function() {    return new OperationAdd;                //子类创建运算类实例};

 原型式继承实现搭建工厂方法

//原型式继承使用的辅助函数var clone = function(object) {    //检查object是不是字面量对象    if(Object.prototype.toString.call(object) !== '[object Object]') {        throw new Error('在clone函数中传递的不是字面量对象');    }    var F = function() {};    F.prototype = object;    return new F();};//模仿抽象类var iFactory = {    getResult: function(a, b) {        //获取运算类对象        var oper = this.factoryMethod();        //通过具体运算类,返回结果        return oper.getResult(a, b);    },    factoryMethod: function() {        throw new Error('子类需要实现factoryMethod方法');    }};//原型式继承iFactory对象var subFactory = clone(iFactory);//覆盖iFactory中的方法subFactory.factoryMethod = function() {    return new OperationSub();};

 现在已经把整个程序业务写好了,看看怎样使用我们刚才所创建的一大推东西

//--------------------- test --(function() {    try{        //创建加法工厂实例        var addFactory = new AddFactory();        //用加法工厂创建出来的加法类实现两参数相加        var result = addFactory.getResult(4, 3);        console.log(result);        //原型式继承的测试        //console.log(subFactory.getResult(3, 1));          }    catch(e) {        console.log(e.message);            }})();

客户端使用是不是很简单呢。 

项目开发中遇到的问题:

在辅助函数/对象中大量使用了throw new Error()语句,当错误发生时会允许你自定义错误提示信息。但这个提示却不能定位的那么完美。

 

 

 

 

 

转载于:https://www.cnblogs.com/mackxu/archive/2013/03/15/factorymehod2.html

你可能感兴趣的文章
Android 将drawable下的图片转换成bitmap、Drawable
查看>>
介绍Win7 win8 上Java环境的配置
查看>>
移动、联通和电信,哪家的宽带好,看完你就知道该怎么选了!
查看>>
Linux设置环境变量的方法
查看>>
Atitit.进程管理常用api
查看>>
构建自己的项目管理方案
查看>>
利用pca分析fmri的生理噪声
查看>>
div水平居中且垂直居中
查看>>
epoll使用具体解释(精髓)
查看>>
AndroidArchitecture
查看>>
安装Endnote X6,但Word插件显示的总是Endnote Web"解决办法
查看>>
python全栈 计算机硬件管理 —— 硬件
查看>>
大数据学习
查看>>
简单工厂模式
查看>>
Delphi7编译的程序自动中Win32.Induc.a病毒的解决办法
查看>>
Objective-C 【关于导入类(@class 和 #import的区别)】
查看>>
倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-点击运行按钮进入到运行状态报错Error starting TwinCAT System怎么办 AdsWarning1823怎么办...
查看>>
【转】javascript 中的很多有用的东西
查看>>
Centos7.2正常启动关闭CDH5.16.1
查看>>
Android 监听返回键、HOME键
查看>>