-
要点:
- 定义变量不会污染外部
- 能够作为一个模块调用
- 遵循开闭原则
-
什么是好的封装:
- 变量外部不可见
- 调用接口使用
- 留出扩展接口
-
封装对象时的设计模式
工厂模式
目的:方便我们大量创建对象(大量多个)
应用场景:当某一个对象需要经常创建的时候(分页;弹窗等)
一、基本结构:
function Factory(type){
switch (type){
case 'type1':
return new Type1();
case 'type2':
return new Type2();
case 'type3':
return new Type3();
}
}
ps:工厂模式就是写一个方法,只需要调用这个方法,就能拿到你要的对象
二、工厂模式示例
例子:实现一个多彩弹框
需求:弹窗有多种,他们之间存在内容和颜色的差异,
// 放在一个匿名自执行函数,向外部暴露pop
(function(){
// 创建一个弹框工厂
function pop(type,content,color){
// 判断使用者是否new了这个弹框,健壮性
if(this instanceof pop){
return new this[type](content,color)
}else{
return new pop(type,content,color)
}
}
pop.prototype.infoPop = function(){}
pop.prototype.confirmPop = function(){}
pop.prototype.cancelPop = function(){}
window.pop = pop
})()
// 外部直接调用
pop('infoPop','hello','blue')
例子:源码示例jQuery
需求:jQuery需要操作dom,每一个dom都是一个jq对象,
(function(){
var jQuery = function(selectory,context){
// 参数接受选择器和上下文
// 内部其实返回了这么一个init对象,假如new了本身会递归循环
return new jQuery.fn.init(selectory,context);
};
jQuery.fn = jQuery.prototype = {
init:function(){
}
}
jQuery.fn.init.prototype = jQuery.fn;
// jq的各种方法模块扩展进去 extend方法 作用:拷贝
jQuery.extend = jQuery.fn.extend = function(){
}
jQuery.extend({
})
// 挂载到window
window.$ = window.jQuery = jQuery;
})();
建造者模式
目的:需要组合出一个全局对象(精细化一个)
应用场景:当要创建单个又庞大的组合对象时(轮播图)
一:基本结构
//模块1
function Mode1(){
}
//模块2
function Mode2(){
}
// 最终的使用类
function Final(){
this.mode1 = new Mode1();
this.mode2 = new Mode2();
}
ps:把一个复杂的类各个部分,拆分成独立的类,然后再在最终类里组合到一块,Final为最终给出去的类
二:建造者模式示例
例子:编辑器插件
需求:有一个编辑器插件,初始化的时候需要大量参数,而且内部功能很多,
// 最终new的编辑器类
function Editor(){
// 初始化
this.initHtml = new initHtml();
this.fontControll = new fontControll();
this.stateControll = new stateControll();
};
// 初始化html类
function initHtml(domStyle){
this.template='<div style={{editorStyle}}><div></div><div><textarea style={{areaSyle}}/></div></div>';
}
initHtml.prototype.initStyle = function(){
}
initHtml.prototype.renderDom = function(){
}
// 字体控制类
function fontControll(){
}
fontControll.prototype.changeColor = function(){
}
fontControll.prototype.changeFontsize = function(){
}
// 状态控制类
function stateControll(){
// 假设有个状态数组和当前状态index
this.state = [];
this.nowstate = 0
}
stateControll.prototype.saveState = function(){
}
stateControll.prototype.stateBack = function(){
// 我们可以直接操作其他类
var state = this.state[this.nowstate-1];
this.fontControll.changeColor(state.color);
this.fontControll.changeFontsize(state.color);
}
stateControll.prototype.stateGo = function(){
}
window.Editor = Editor;
例子:Vue初始化
需求:内部众多模块,过程复杂
function Vue(){
if(!(this instanceof Vue)){
// 你需要new操作符
warn('Vue is a constructor and should be called with the `new` keyword');
};
// 传入用户配置参数初始化
this._init(options);
}
// 用方法混入实例
initMixin(Vue);
stateMixin(Vue);
eventsMixin(Vue);
lifecycleMixin(Vue);
renderMixin(Vue);
export function install (_Vue) {
if (Vue && _Vue === Vue) {
if (process.env.NODE_ENV !== 'production') {
console.error(
'[vuex] already installed. Vue.use(Vuex) should be called only once.'
)
}
return
}
Vue = _Vue
applyMixin(Vue)
}
单例模式
目的:需要确保全局只有一个对象
应用场景:为了避免重复新建,避免多个对象存在互相干扰
一:基本结构
//我们要实例化的对象
let Singleton = function(name){
this.name = name;
}
//在singleton上挂载一个getInstance方法
Singleton.getInstance = function(name){
// 如果已经实例化过了就直接返回instance
if(this.instance){
return this.instance
}
// 定义instance为实例化对象返回
return this.instance = new Singleton(name);
}
ps:通过定义一个方法,使用时只允许通过此方法拿到存在内部的同一实例化对象,单例模式写法不固定,
二:单例模式示例
例子:写一个全局数据储存对象
需求:这个储存者只有一个,不然得进行同步,增加复杂度
function store(){
// 判断有没有静态的install属性
if(store.install){
return store.install;
}
// 没有就把他指向this 对象本身
store.install = this;
this.store = {
}
}
store.install = null;
例子:Vue-router
需求:保障只有一个
// 现在外层定义个_Vue变量
let _Vue;
function install (_Vue) {
// 判断有没有installed的属性并且_Vue被赋值过了
if (install.installed && _Vue === Vue) return
install.installed = true
_Vue = Vue
}