【JS设计模式笔记】给我一张名片-工厂方法模式(创建型)
广告展现
例如,关于计算机培训广告资源需要投放,一批是Java的用绿色字体,一批是PHP的,用黄色字体,红色背景。
// 创建Java学科类
var Java = function (content) {
// 将内容保存在content里面以备后面使用
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'green';
document.getElementById('container').appendChild(div);
})(content);
}
// 创建PHP学科类
var Php = function(content) {
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'yellow';
div.style.background = 'red';
document.getElementById('container').appendChild(div);
})(content);
}
刚写完,又来了一批广告,关于JavaScript的,要求背景色是粉色的,于是用简单工厂模式来实现。
// 创建Java学科类
var Java = function (content) {
// 将内容保存在content里面以备后面使用
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'green';
document.getElementById('container').appendChild(div);
})(content);
}
// 创建PHP学科类
var Php = function(content) {
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.color = 'yellow';
div.style.background = 'red';
document.getElementById('container').appendChild(div);
})(content);
}
// 创建javascript学科类
var Javascript = function(content) {
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.background = 'pink';
document.getElementById('container').appendChild(div);
})(content);
}
// 学科类工厂
function Jobfactory(type,content) {
switch(type) {
case 'java':
return new Java(content);
case 'php':
return new Php(content);
case 'Javascript':
return new Javascript(content);
}
}
// 测试示例
new Jobfactory('Javascript','javascript哪家强!')
刚写完不久,又来了一批广告,UI学科的,需要红色边框.... 沉默了....
方案的择决
现在我发现,只要每次新来一批广告 ,我除了要添加类,还要修改工厂函数,这个时候工厂方法模式就出现了。我们可以将工厂方法看做是一个实例化对象的工厂类。安全起见,采用安全模式类。
安全模式类
安全模式类解决如下示例问题:
var Demo = function() {}
Demo.prototype = {
show: function() {
console.log('成功获取');
}
}
var d = new Demo();
d.show(); // 成功获取
var d2 = Demo();
d2.show(); // Uncaught TypeError: Cannot read properties of undefined (reading 'show')
为了避免出现上述问题,我们在构造函数开始执行时候,先判断当前对象this指代的是不是类(Demo),我们永生instanceof判断。
var Demo = function() {
if(!(this instanceof Demo)) {
return new Demo();
}
}
Demo.prototype = {
show: function() {
console.log('成功获取');
}
}
var d = new Demo();
d.show(); // 成功获取
var d2 = Demo();
d2.show(); // 成功获取
有了安全模式,我们就可以把这种技术应用到工厂方法中。
安全的工厂方法
// 安全模式创建的工厂类
var Factory = function(type,content) {
if(this instanceof Factory) {
return new this[type](content);
} else {
return new Factory(type,content);
}
}
// 工厂原型中设置创建所有类型数据对象的基类
Factory.prototype = {
Java: function(content) {
},
php: function(content) {
},
Javascript: function(content) {
},
UI: function(content) {
this.content = content;
(function(content){
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid red';
document.getElementById('container').appendChild(div);
})(content);
}
}
// 示例
Factory('UI','UI哪家强')
这样如果我们后面想其他其他类,只需要写在Factory这个工厂类的原型里面就可以了。
这就好比你在Factory类的原型上注册了一张名片,以后需要哪个类,只需要拿着这张名片,查找上面的信息就能找到这个类了。所有就不用担心使用的时候到不到基类了。
我们也可以这样使用:
// 示例
var data = [
{type: 'Javascript',content: 'Javascript哪家强'},
{type: 'Javascript',content: 'Javascript哪家强'},
{type: 'php',content: 'php哪家强'},
{type: 'UI',content: 'UI哪家强'},
{type: 'UI',content: 'UI哪家强'}
]
for(var i = 0; i < data.length; i++) {
Factory(data[i].type,data[i].content);
}