简单工厂模式
简单工厂模式,又叫静态工厂模式,由一个工厂创建某一种对象的实例,主要用来创建同一种对象
对不同类的实例化
有一个需求,要创建登录提示框,登录的确认框,登录成功的提示框,因为逻辑不完全相同,所以我们写成三个类
const LoginAlter = function (text) { this.context = text } // 为什么方法很多时候都要写在prototype里,而不直接写在LoginAlter中呢 // 因为我们可能构建很多个LoginAlter的实例,如果直接写在对象了,每次实例化就都会创建一遍,浪费内存 // 但是如果我们写在原型中,实例化的时候是不会单独创建的,调用直接找到原型里,就可以实现共用了 LoginAlter.prototype.show = function () { // 显示警示框 } // 登录不规范警示 const userNameAlert = new LoginAlter("用户名不能多于16个字符") ============================================================================================================= // 密码错误登录确认框 const LoginConfirm = function (text) { this.context = text } LoginConfirm.prototype.show = function () { // 显示确认框 } // 登录错误确认重新登录 const loginFailConfrim = new LoginAlter("登录密码错误") ============================================================================================================= // 登陆成功提示框 const LoginPrompt = function (text) { this.context = text } LoginConfirm.prototype.show = function () { // 显示提示框 }
但当类似的需求变多时,越来越多的类,很难记,怎么才能放在一起呢?
可以采用简单工厂模式进行封装
const PopFactory = function (name, text) { switch(name){ case "alter": return new LoginAlter(text) case "confirm": return new LoginConfirm(text) case "prompt": return new LoginPrompt(text) } }
创建相似对象
上述三个类虽然封装起来了便于使用,但是这三个类相似度很高,所以可以用另一种简单工厂模式创建一个对象,通过创建一个新的对象,然后包装增强其属性和功能来实现
const createPop = function (type, text) { let o = new Object() o.context = text o.show = function (text) { alert(text) } if(type === "alter"){ // 警示框差异部分 } if(type === "prompt"){ // 提示框差异部分 } if(type === "confirm"){ // 确认框差异部分 } return o }
安全的工厂方法
为了保证安全,防止忘记或使用错误,没有通过new创建实例,导致this指向外部造成污染,应使用安全模式创建,直接看代码很好理解
const Demo = function () { if(!(this instanceof Demo)){ return new Demo() } }
有时,因为需求一直变化,导致使用不同类的工厂模式要一直重构,一直添加创建新的类,修改switch,并非一个很好的方式
我们可以借用原型的方式的方式添加,更为直观简洁
// 安全的工厂方法 const Factory = function (type, content) { if(this instanceof Factory){ let s = new this[type](content) return s }else{ return new Factory(type, content) } }
在原型上添加初始不同的对象
Factory.prototype = { Java: function (content) { // Java }, JavaScript: function (content) { // JavaScript }, UI: function (content) { // 注意,若不用安全模式,此处this就可能会指向全局,造成安全隐患 this.content = content; //此处不加分号,会默认执行content(),闭包反而成了个累赘 (function (content) { let div = document.createElement("div") div.innerHTML = content div.style.border = "1px solid red" document.getElementById("container").appendChild(div) })(content) }, php: function (content) { // php }, }
创建一个实例,如下图,创建成功
const test = new Factory("UI", "UI training courses")
若此时需要添加一个Python的需求,只需要在原型上添加即可
Factory.prototype.python = function(content){ this.content = content }