在某个场景中,我们有两个控制器对象:
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