工厂模式设计
2017-09-27 本文已影响0人
小建哥哥
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>工厂设计模式</title>
<!--
@theme: javascript高级 工厂模式设计
@autor:EthanCoco
@date:2015-11-21
@email:lijianlin0204@163.com
-->
<script type=text/javascript charset=utf-8>
//创建一个命名空间
var LJL = {};
/**
*建一个接口
*接口需要两个参数
*参数1: 接口的名字(string)
*参数2: 方法名称(数组(string))
*/
LJL.Interface = function(name,methods){
if(arguments.length !== 2){//判断接口参数个数是否正确
throw new Error("参数个数不正确!");
}
this.name = name;
this.methods = [];//定义一个内置的空数组接受方法名称里的元素
for(var i = 0;i < methods.length;i++){
if(typeof methods[i] !== 'string'){
throw new Error("方法名称错误,必须是字符串类型!");
}
//把传入参数的元素全部放到内置的methods中去
this.methods.push(methods[i]);
}
};
/**
*接口静态方法
*参数:object
*检验接口里的方法是否实现
*如果通过不做任何操作,如果不通过,抛出error
*目的:检测方法是否全部实现
*object 要求参数必须有两个以上
*一个是对象实例
*其它是要检验的接口对象
*/
LJL.Interface.checkMethodsIsPass = function(object){
if(arguments.length < 2){//判断参数,如果参数小于2,抛出异常
throw new Error("要求参数必须有两个以上@param1=实例对象,其它参数是接口对象!");
}
//获得接口实例对象
for(var i = 1;i<arguments.length;i++){//i=1是因为第二个参数是需要检测的接口
var instanceInterface = arguments[i];
//判断参数是否是接口对象
if(instanceInterface.constructor !== LJL.Interface){
throw new Error("参数是不是接口对象!");
}
//如果是,检测接口对象里的方法是否实现
for(var j = 0;j<instanceInterface.methods.length;j++){
//用历史变量接受一个方法的名称,名称是字符串,如果不是就抛出error
var methodName = instanceInterface.methods[j];
//object[key]表示的就是方法
//方法是一个函数,需要判断
if(!object[methodName] || typeof object[methodName] !== 'function'){
throw new Error("这个方法 '" + methodName + "' 找不到!");
}
}
}
};
/**
* 继承方法
* @param {Object} sub
* @param {Object} sup
*/
LJL.extend=function(sub ,sup){
// 目的: 实现只继承父类的原型对象
var F = new Function(); // 1 创建一个空函数 目的:空函数进行中转
F.prototype = sup.prototype; // 2 实现空函数的原型对象和超类的原型对象转换
sub.prototype = new F(); // 3 原型继承
sub.prototype.constructor = sub ; // 4还原子类的构造器
//保存一下父类的原型对象: 一方面方便解耦 另一方面方便获得父类的原型对象
sub.superClass = sup.prototype; //自定义一个子类的静态属性 接受父类的原型对象
//判断父类的原型对象的构造器 (加保险)
if(sup.prototype.constructor == Object.prototype.constructor){
sup.prototype.constructor = sup ; //手动欢迎父类原型对象的构造器
}
};
////////////////////////////////////////////////
//以上都是为工厂设计模式做必要的准备
////////////////////////////////////////////////
//思路整理
/**
*设计一个买电脑的工厂设计模式
*首先,得有一个“工厂”;
*其次,工厂用来“生产电脑”;
*然后,电脑需要“卖出去”;
*继续,卖出去需要一个“专卖店”
*最后,买电脑的人到什么样的商店去“买什么样的电脑”
*/
//生产电脑的工厂 目的:生产电脑
var PCFactory = {
//里面有生产电脑的方法
createPC : function(type){//type 动态生产电脑类型,即客户需要的电脑生产
//利用eval动态创建传入类型的实例对象
var pc = eval('new '+type+'()');
//电脑在生产的时候就需要检测是否合格!
//第一个参数是电脑的实例对象
//第二个参数是接口的实例对象
LJL.Interface.checkMethodsIsPass(pc,PCInterface);
return pc;
}
};
//创建接口实例对象
//接口需要有两个参数
//一个是接口的实例对象,一个是方法(数组),open(开机),run(运行)
var PCInterface = new LJL.Interface('PCInterface',['open','run']);
//创建一个电脑的基类
function BasePC(){}
//在原型对象上实现方法
BasePC.prototype = {
constructor : BasePC,//还原构造器
open : function(){
alert(this.constructor.name + "...open");
},
run : function(){
alert(this.constructor.name + "...run");
}
};
//电脑有不同的品牌,不同的专卖店提供不同的电脑
//创建一个抽象的基类专卖店
function PCShop(){}
PCShop.prototype = {
constructor : PCShop ,
//买电脑的方法
sellPC:function(type){
this.abstractSellPC(type);
} ,
abstractSellPC: function(){
throw new Error('this method is abstract...');
}
};
//创建不同品牌的专门店
///////////////////////////////////////////////////
//戴尔专卖店
function DellPCShop(){}
//每个店都有卖电脑的方法,所以我们继承PCShop里的方法
LJL.extend(DellPCShop,PCShop);
//电脑专卖店有不同型号的dell电脑
DellPCShop.prototype = {
constructor : DellPCShop,
sellPC : function(type){
var pc ;
var pctypes = ['dellx1','dellx5','dellx8'];//所有dell电脑的型号
for(i in pctypes){
//判断商店是否有你要的型号
if(pctypes[i] === type){
pc = PCFactory.createPC(type);
break;
}else{
throw new Error("没有你要的型号!");
}
}
return pc;
}
};
//dell电脑不同型号的方法检测实现
//检测不同品牌的电脑
function dellx1(){}
LJL.extend(dellx1,BasePC); //继承基类的方法
function dellx5(){}
LJL.extend(dellx5,BasePC);
function dellx8(){}
LJL.extend(dellx8,BasePC);
//////////////////////////////////////////////
var shop = new DellPCShop();
var pc = shop.sellPC('dellx1');
pc.open();
</script>
</head>
<body>
</body>
</html>