JavaScript 디자인 모드(데코더 모드)

16751 단어

1. 전통적인 대상 언어를 위한 장식자 모드를 시뮬레이션한다.


가령 우리가 비행기 대전의 게임을 작성하고 있다면, 경험치가 증가함에 따라 우리가 조작하는 비행기 대상은 더욱 강한 비행기로 업그레이드될 수 있다. 처음에 이 비행기들은 일반적인 총알만 발사할 수 있고, 2급으로 올라갈 때 미사일을 발사할 수 있으며, 3급으로 올라갈 때 원자탄을 발사할 수 있다.
//  
var Plane = function(){
}
Plane.prototype.fire = function(){ 
  console.log( ' ' );
}

//  , :
var MissileDecorator = function( plane ){ 
  this.plane = plane;
}
MissileDecorator.prototype.fire = function(){ 
  this.plane.fire();
  console.log( ' ' );
}

var AtomDecorator = function( plane ){ 
  this.plane = plane;
}
AtomDecorator.prototype.fire = function(){ 
  this.plane.fire();
  console.log( ' ' );
}

//  
var plane = new Plane();
plane = new MissileDecorator( plane ); 
plane = new AtomDecorator( plane );
plane.fire();
//  :  、 、 

이렇게 대상에게 동적으로 직책을 추가하는 방식은 진정으로 대상 자체를 바꾸지 않고 대상을 다른 대상에 넣는다. 이런 대상은 하나의 체인 방식으로 인용하여 하나의 집합 대상을 형성한다.이 대상들은 모두 같은 인터페이스(fire 방법)를 가지고 있으며, 요청이 체인의 어떤 대상에 도달할 때, 이 대상은 자신의 조작을 실행하고, 그 다음에 요청을 체인의 다음 대상에게 전달합니다. 
장식자의 대상과 장식된 대상은 일치하는 인터페이스를 가지고 있기 때문에 이 대상을 사용하는 고객에게는 투명하다. 장식된 대상도 장식된 것을 알 필요가 없다. 이런 투명성은 우리로 하여금 임의의 여러 개의 장식자 대상을 귀속적으로 끼워 넣을 수 있게 한다

2. 장식자도 포장기


기능적으로는 decorator가 이 모델을 잘 묘사할 수 있지만 구조적으로는 wrapper의 표현이 더욱 적절하다.장식자 모드는 한 대상을 다른 대상에 삽입하는데 실제로는 이 대상이 다른 대상에 의해 포장되어 하나의 포장 체인을 형성하는 것과 같다.요청은 이 체인에 따라 순서대로 모든 대상에 전달되며, 모든 대상은 이 요청을 처리할 기회가 있다

3. 자바스크립트로 돌아가는 장식자


JavaScript 언어의 동적 변경 대상은 상당히 쉽습니다. 우리는 대상이나 대상의 어떤 방법을 직접 고칠 수 있습니다. "클래스"를 사용하여 장식자 모드를 실현할 필요가 없습니다.
var plane = {
  fire: function(){
    console.log( ' ' ); 
  }
}
var missileDecorator = function(){ 
  console.log( ' ' );
}
var atomDecorator = function(){ 
  console.log( ' ' );
}
var fire1 = plane.fire;
plane.fire = function(){ 
  fire1();
  missileDecorator(); 
}
var fire2 = plane.fire;
plane.fire = function(){ 
  fire2();
  atomDecorator(); 
}
plane.fire();
//  :  、 、 

4. AOP로 함수 꾸미기

Function.prototype.before = function( beforefn ){
  //  
  var __self = this;
  //  " " 
  return function(){ 
    //  , this ,  
    //
    beforefn.apply( this, arguments ); 
    return __self.apply( this, arguments ); //  , //  this 
  } 
}
Function.prototype.after = function( afterfn ){ 
  var __self = this;
  return function(){
    var ret = __self.apply( this, arguments ); 
    afterfn.apply( this, arguments );
    return ret;
  } 
};

Function.prototype.before는 함수를 매개 변수로 받아들입니다. 이 함수는 새로 추가된 함수입니다. 새로 추가된 기능 코드를 불러옵니다.다음에 현재this를 저장합니다. 이this는 원 함수를 가리키고'에이전트'함수를 되돌려줍니다. 이'에이전트'함수는 구조적으로 에이전트일 뿐 에이전트의 직책을 맡지 않습니다(예를 들어 제어 대상의 방문 등).그것의 작업은 요청을 각각 새로 추가된 함수와 원함수에 전달하고 그들의 실행 순서를 확보하여 새로 추가된 함수를 원함수 앞에서 실행하도록 하는 것이다. 그러면 동적 장식 효과를 실현할 수 있다.
//  1:
document.getElementById = document.getElementById.before(function() {
  alert (1);
});
var button = document.getElementById('button');
console.log(button)

//  2( window.onload):
window.onload = function(){ 
  alert (11);
}
window.onload = ( window.onload || function(){} ).before(function(){ 
  alert (22);
}).after(function(){ 
  alert (33);
}).after(function(){ 
  alert (44);
});

언급할 만한 것은 위의 AOP 구현은 Function에서 이루어졌다는 것이다.prototype에 before와 after 방법을 추가하지만 많은 사람들이 이런 오염된 원형 방식을 좋아하지 않는다. 그러면 우리는 원함수와 새로운 함수를 매개 변수로 before나 after 방법에 전달할 수 있다.
var before = function( fn, beforefn ){ 
  return function(){
    beforefn.apply( this, arguments );
    return fn.apply( this, arguments );
  }
} 
var a = before( function(){
    alert (3)
  }, function(){
    alert (2)
  }
);
a = a();

5. AOP의 응용 사례


업무 코드의 작성이든 프레임워크 차원이든 우리는 행위를 직책에 따라 입도가 더 가는 함수로 나눈 다음에 장식을 통해 그것들을 한데 합칠 수 있다. 이것은 우리가 느슨한 결합과 높은 복용성을 가진 시스템을 작성하는 데 도움이 된다.업무 코드와 데이터 통계 코드를 분리하는 것은 어떤 언어에서든 AOP의 고전적인 응용 프로그램 중의 하나이다.

5.1: 만약에 지금 우리가 단추를 클릭한 후에 로그인 부층을 열고 데이터에 보고하는 것을 책임져야 한다고 가정하면 우리는 showLogin 함수에서 두 가지 측면의 기능을 보았는데 여기서 한 함수에 결합되었다.

{/*  */}
var showLogin = function(){ 
  console.log( ' ' ); 
  log( this.getAttribute( 'tag' ) );
}
var log = function( tag ){
  console.log( ' : ' + tag );
  // (new Image).src = 'http:// xxx.com/report?tag=' + tag;   //  
}
document.getElementById( 'button' ).onclick = showLogin;

//   AOP , :
var showLogin = function(){ 
  console.log( ' ' );
}
var log = function(){
  console.log( ' : ' + this.getAttribute( 'tag' ) );
}
showLogin = showLogin.after(log); //  
document.getElementById('button').onclick = showLogin;

5.2: 플러그인 양식 검증


   :
   : 
   


전통적인 폼 검증의 쓰기 방법:formSubmit 함수는 이곳에서 두 가지 직책을 맡았고 aax 요청을 제출하는 것 외에 사용자 입력의 합법성을 검증해야 한다.이런 코드는 함수가 비대해지고 직책이 혼란스러우며 둘째, 복용성은 말할 것도 없다.
var username = document.getElementById( 'username' ),
    password = document.getElementById( 'password' ), 
    submitBtn = document.getElementById( 'submitBtn' );
var formSubmit = function(){
  if ( username.value === '' ){
    return alert ( ' ' ); 
  }
  if ( password.value === '' ){
    return alert ( ' ' );
  }
  var param = {
    username: username.value, 
    password: password.value
  }
  ajax( 'http:// xxx.com/login', param );
}
submitBtn.onclick = function(){ 
  formSubmit();
}

개조된 쓰기 방법은 이 코드에서 입력과 제출표를 검사하는 코드가 완전히 분리되어 더 이상 결합 관계가 없습니다.formSubmit=formSubmit.before(validata)라는 코드는 검사 규칙을 formSubmit 함수에 동적으로 연결하기 전에validata는 삽입 및 사용 가능한 함수가 되고 심지어 프로필 형식으로 작성될 수 있으며 이 두 함수를 분리하여 유지하는 데 유리하다.다시 전략 모델을 이용하여 조금만 개조하면 우리는 이러한 검사 규칙을 모두 플러그인 형식으로 작성하여 서로 다른 프로젝트에 사용할 수 있다.
Function.prototype.before = function( beforefn ){
  var __self = this; 
  return function(){
    if ( beforefn.apply( this, arguments ) === false ){
    // beforefn   false   return,  return;
    }
    return __self.apply( this, arguments ); 
  }
}
var validata = function(){
  if ( username.value === '' ){
    alert ( ' ' );
    return false; 
  }
  if ( password.value === '' ){ 
    alert ( ' ' ); 
    return false;
  } 
}
var formSubmit = function(){ 
  var param = {
    username: username.value,
    password: password.value
  }
  ajax( 'http:// xxx.com/login', param ); 
}
formSubmit = formSubmit.before( validata );
submitBtn.onclick = function(){ 
  formSubmit();
}

6: 장식자 모드와 프록시 모드


장식자 모드와 프록시 모드의 구조는 매우 비슷해 보인다. 이 두 가지 모드는 대상에 어느 정도의 간접 인용을 제공하는지 설명하고 그들의 실현 부분은 다른 대상에 대한 인용을 보류하며 그 대상에 요청을 보낸다.
에이전트 모델과 장식자 모델의 가장 중요한 차이점은 그들의 의도와 디자인 목적에 있다.에이전트 모델의 목적은 본체에 직접 접근하는 것이 불편하거나 수요에 부합되지 않을 때 이 본체에 대체자를 제공하는 것이다.본체는 관건적인 기능을 정의하고, 에이전트는 그것에 대한 접근을 제공하거나 거부하거나, 본체에 접근하기 전에 추가 작업을 합니다.장식자 모델의 역할은 대상의 동적 가입 행위이다.다시 말하면 프록시 모델은 일종의 관계(Proxy와 그 실체 간의 관계)를 강조하는데 이런 관계는 정태적으로 표현할 수 있다. 즉, 이런 관계는 처음부터 확정될 수 있다는 것이다.장식자 모드는 처음에 대상의 모든 기능을 확정할 수 없을 때 사용됩니다.프록시 모드는 보통 프록시 본체의 인용만 있고 장식자 모드는 긴 장식 체인을 형성한다.

좋은 웹페이지 즐겨찾기