今回はMediatorパターン。Mediatorは仲介者で、オブジェクト間の連携を一手に担ってくれます。
下例のようなGUIプログラミングによく使われるそうです。MVCモデルに通じますね。
今回はGUIが絡んでいるので、JavaScriptで書いてみました。
JavaScriptはほぼ初挑戦なので、変な実装とかあったら指摘もらえると助かります。
(JavaScriptのOOPってこんなにしんどいんですか?)
実行結果
ソースコード
// id="my_content" のelementがあると仮定している
function onLoad(){
var container = document.getElementById("my_content");
var loginform = new LoginForm();
loginform.appendInto(container);
}
// class declaration
function ColleagueInputButton(){ // implements Colleague Interface
this.initialize.apply(this, arguments);
}
ColleagueInputButton.prototype = {
initialize:
function(caption){
this.content = document.createElement('input');
this.content.setAttribute('type', 'button');
this.content.setAttribute('value', caption);
}
,appendInto:
function(parentContainer){
parentContainer.appendChild(this.content);
}
,setMediator: // Colleague Interface method
function(mediator){
this.content.onclick = mediator.onClick;
}
,setColleagueEnabled: // Colleague Interface method
function(enabled){
this.content.disabled = !enabled;
}
};
// class declaration
function ColleagueInputTextField(){ // implements Colleague Interface
this.initialize.apply(this, arguments);
}
ColleagueInputTextField.prototype = {
initialize:
function(text, columns, passwordtype){
this.content = document.createElement('input');
if(passwordtype){
this.content.setAttribute('type', 'password');
}else{
this.content.setAttribute('type', 'text');
}
this.content.setAttribute('value', text);
this.content.setAttribute('size', columns);
}
,appendInto:
function(parentContainer){
parentContainer.appendChild(this.content);
}
,getText:
function(){
return this.content.value;
}
,setText:
function(text){
this.content.value = text;
this.content.onchange();
}
,setMediator: // Colleague Interface method
function(mediator){
this.content.onchange = mediator.colleagueChanged;
}
,setColleagueEnabled: // Colleague Interface method
function(enabled){
this.content.disabled = !enabled;
if(enabled){
this.content.setAttribute('style', 'background-color: #FFF;');
}else{
this.content.setAttribute('style', 'background-color: #EEE;');
}
}
};
// class declaration
function ColleagueInputRadioButton(){ // implements Colleague Interface
this.initialize.apply(this, arguments);
}
ColleagueInputRadioButton.prototype = {
initialize:
function(caption, groupname, state){
this.content = document.createElement('input');
this.content.setAttribute('type', 'radio');
this.content.setAttribute('name', groupname);
this.content.defaultChecked = state;
}
,appendInto:
function(parentContainer){
parentContainer.appendChild(this.content);
}
,isChecked:
function(){
return this.content.checked;
}
,setMediator: // Colleague Interface method
function(mediator){
this.content.onchange = mediator.colleagueChanged;
}
,setColleagueEnabled: // Colleague Interface method
function(enabled){
this.content.disabled = !enabled;
}
};
// class declaration
function LoginForm(){ // implements Mediator Interface
this.radioGuest = null;
this.radioLogin = null;
this.textUser = null;
this.textPass = null;
this.buttonOK = null;
this.buttonCancel = null;
this.initialize.apply(this, arguments);
}
LoginForm.prototype = {
initialize:
function(){
self = this;
this.content = document.createElement('form');
this.createColleagues();
this.radioGuest.appendInto(this.content);
span = document.createElement('span');
span.innerHTML = "Guest";
this.content.appendChild(span);
this.radioLogin.appendInto(this.content);
span = document.createElement('span');
span.innerHTML = "Login";
this.content.appendChild(span);
this.content.appendChild(document.createElement('br'));
span = document.createElement('span');
span.innerHTML = "Username: ";
this.content.appendChild(span);
this.textUser.appendInto(this.content);
this.content.appendChild(document.createElement('br'));
span = document.createElement('span');
span.innerHTML = "Password: ";
this.content.appendChild(span);
this.textPass.appendInto(this.content);
this.content.appendChild(document.createElement('br'));
this.buttonOK.appendInto(this.content);
this.buttonCancel.appendInto(this.content);
this.colleagueChanged();
}
,appendInto:
function(parentContainer){
parentContainer.appendChild(this.content);
}
,createColleagues: // Mediator Interface method
function(){
this.radioGuest = new ColleagueInputRadioButton("Guest", "usertype", true);
this.radioLogin = new ColleagueInputRadioButton("Login", "usertype", false);
this.textUser = new ColleagueInputTextField("", 10);
this.textPass = new ColleagueInputTextField("", 10, true);
this.buttonOK = new ColleagueInputButton("OK");
this.buttonCancel = new ColleagueInputButton("Cancel");
this.radioGuest.setMediator(this);
this.radioLogin.setMediator(this);
this.textUser.setMediator(this);
this.textPass.setMediator(this);
this.buttonOK.setMediator(this);
this.buttonCancel.setMediator(this);
}
,colleagueChanged: // Mediator Interface method
function(){
if(self.radioGuest.isChecked() === true){
self.textUser.setColleagueEnabled(false);
self.textPass.setColleagueEnabled(false);
self.buttonOK.setColleagueEnabled(true);
}else{
self.textUser.setColleagueEnabled(true);
// and also needs to check textUser&textPass
if(self.textUser.getText().length === 0){
self.textPass.setColleagueEnabled(false);
self.buttonOK.setColleagueEnabled(false);
}else{
self.textPass.setColleagueEnabled(true);
if(self.textPass.getText().length === 0){
self.buttonOK.setColleagueEnabled(false);
}else{
self.buttonOK.setColleagueEnabled(true);
}
}
}
}
,onClick:
function(){
if(this.value === "Cancel"){
self.textUser.setText("");
self.textPass.setText("");
}
else{
if(self.radioGuest.isChecked() === true){
alert("Hello, Guest!");
}else{
alert("Hello, "+self.textUser.getText()+"!\nYour pass is "+self.textPass.getText()+", right??");
}
}
}
};
window.onload = onLoad;
0 件のコメント:
コメントを投稿