在某个场景中,我们有两个控制器对象:
1.用来操作网页中的登录表单;
2.用来与服务器进行通信.
类设计模式
// 把基础的函数定义在名为Controller的类中,然后派生两个子类LoginController和AuthController.
// 父类
function Controller() {
this.errors = [];
}
Controller.prototype.showDialog = function(title, msg) {
// 给用户显示标题和消息
};
Controller.prototype.success = function(msg) {
this.showDialog("Success", msg);
};
Controller.prototype.failure = function(err) {
this.error.push(err);
this.showDialog("Error", err);
};
// 子类
function LoginController() {
Controller.call(this);
}
// 把子类关联到父类
LoginController.prototype = Object.create(Controller.prototype);
LoginController.prototype.getUser = function() {
return document.getElementById("login_username").value;
};
LoginController.prototype.getPassword = function() {
return document.getElementById("login_password).value;
};
LoginController.prototype.validateEntry = function (user, pw) {
user = user || this.getUser();
pw = pw || this.getPassword();
if(!(user && pw)) {
return this.failure(
"Please enter a username & password!"
);
}
else if (pw.length < 5) {
return this.failure(
"Password must be 5+ characters!"
);
}
// return true;
};
// 重写基础failure()
LoginController.prototype.failure = function(err) {
Controller.prototype.failure.call(
this,
"Login invalid: " + err
);
};
// 子类
function AuthController(login) {
Controller.call(this);
// 合成
this.login = login;
}
// 把子类关联到父类
AuthController.prototype = Object.create(Controller.prototype);
AuthController.prototype.server = function (url, data){
return $.ajax({
url: url,
data: data
});
};
AuthController.prototype.checkAuth = function() {
var user = this.login.getUser();
var pw = this.login.getPassword();
if(this.login.validateEntry(user,pw)) {
this.server('/check-auth',{
user:user,
pw: pw
})
.then(this.success.bind(this))
.fail(this.failure.bind(this));
}
};
// 重写基础success()
AnthController.prototype.success = function() {
Controller.prototype.success.call(this, "Authenticated!");
};
// 重写基础的failure()
AuthController.prototype.failure = function(err) {
Controller.prototype.failure.call(this, "Auth Failed: " + err);
};
var auth = new AuthController(
new LoginController() // 合成...
};
auth.checkAuth();
对象关联的设计:
var LoginController = {
errors: [],
getUser: function() {
return document.getElementById("login_username").value;
},
getPassword: function() {
return document.getElementById("login_password").value;
},
validateEntry: function(user, pw) {
user = user || this.getuser();
pw = pw || this.getPassword();
if(!(user && pw)) {
return this.failure("Please enter a username & password!"
);
}
else if(pw.length < 5) {
return this.failure("Password must be 5+ characters!");
}
// 执行到这里说明通过验证
return true;
},
showDialog: function(title, msg) {
// 给用户显示标题和消息
},
failure: function(err) {
this.error.push(err);
this.showDialog("Error", "Login invalid: " + err);
}
};
// 让AuthController委托LoginController
var AuthController = Object.create(LoginController);
AuthController.errors = [];
AuthController.checkAuth = function() {
var user = this.getUser();
var pw = this.getPassword();
if(this.validateEntry(user, pw)) {
this.server('/check-auth", {
user:user,
pw:pw
})
.then(this.accepted.bind(this))
.fail(this.rejected.bind(this));
}
};
AuthController.server = function(url, data) {
return $.ajax({
url: url,
data: data
});
};
AuthController.accepted = function() {
this.showDialog("Success" , " Authenticated!");
};
AuthController.rejected = function(err){
this.failure("Auth Failed: " + err);
};
// 借助对象关联,可以简单地向委托链上添加一个或多个对象.
var controller1 = Object.create(AuthController);
var controller2 = Object.create(AuthController);
更好的语法:
// 在ES6中,可以使用对象字面量的形式来改写繁琐的属性赋值语法
var LoginController = {
errors: [],
getUser() {
//...
},
getPassword() {
//...
}
//...
};
var AuthController = {
errors: [],
checkAuth() {
//...
},
server(url, data) {
//...
}
// ...
};
// 使用Object.setProtptypeOf(...)来修改其原型链[[Prototype]]
Object.setPrototypeOf(AuthController, loginController);
参考《你不知道的JavaScript》(上卷)P178~P183