在某個場景中,我們有兩個控制器對象:
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