>  기사  >  웹 프론트엔드  >  Javascript의 AOP 프로그래밍에 대해 이야기

Javascript의 AOP 프로그래밍에 대해 이야기

黄舟
黄舟원래의
2017-02-25 13:39:061272검색


덕펀치

먼저 AOP 프로그래밍을 이야기하지 말고, 덕펀치 프로그래밍부터 시작해보자.

위키피디아에서 덕펀치라고 검색하면, 꼭 찾아야 할 항목이 몽키패치입니다. 설명에 따르면 몽키패치(monkey patch)라는 단어는 작전 중 조용히 코드를 바꾼다는 뜻의 게릴라 패치(guerrilla patch)에서 유래됐으며 게릴라(guerrilla)라는 단어는 고릴라와 발음이 같고, 후자는 원숭이(전자는 '고릴라'라는 뜻)와 비슷하다는 뜻이다. 마침내 For Monkey 패치로 진화했습니다.

덕펀치(Duck Punch)를 들어본 적이 없다면 덕타이핑(Duck Typing)은 들어보셨을 겁니다. 유명한 예를 들면, 오리를 식별하는 방법:

나는 오리처럼 걷고, 오리처럼 헤엄치고, 오리처럼 꽥꽥거리는 새를 보면 그 새를 오리라고 부릅니다.

네, 오리처럼 꽥꽥거리고 오리처럼 헤엄치는 동물을 찾으면 바로 오리일 거예요!

Javascript의 AOP 프로그래밍에 대해 이야기

이 테스트는 다소 뻔하고 무의미해 보일 수도 있지만 매우 실용적입니다. 그리고 프로그래밍의 문제 유형(Javascript 또는 유사한 동적 언어의 경우 "인터페이스" 또는 "기본 클래스"를 구현하는 방법)을 해결하는 데 사용할 수 있습니다. 과거에 대해서는 전혀 신경 쓸 필요가 없습니다. 메소드 유형이나 매개변수가 사용할 때 필요한지 여부만 고려하면 됩니다.

rree

사실 너무 멀리 가고 있습니다. 표현하고 싶은 것은 오리 펀치입니다. 오리 타이핑에서 진화한 것입니다.

오리처럼 걷고 오리처럼 말하면 오리겠죠? 그런데, 이것은 매우 생생한 농담을 생각나게 합니다:

의 힘을 시험하기 위해. 미국과 홍콩, 중국 본토의 경찰은 유엔이 세 숲에 토끼 세 마리를 배치해 누가 먼저 토끼를 찾는지 세 곳에서 경찰을 감시한다. 과제: 토끼를 찾아보세요. (가운데는 생략...) 결국 어느 나라 경찰 4명만 있었는데, 그들은 하루 동안 마작을 하다가 해질녘에 각자 지휘봉을 들고 비명소리를 들었습니다. 숲에서 나오는 동물들. 담배를 피우며 이야기를 나누며 웃었고, 그 뒤에는 코가 멍들고 얼굴이 부어오른 곰이 죽어가며 말했습니다. “더 이상 때리지 마세요. 그냥 토끼..."

오리펀치이긴 하지만 다소 폭력적이지만 효과적인 방법이다. 코드 구현에 있어서는 원본 코드가 필요한 기능과 호환되도록 만드는 것을 의미합니다. 예를 들어 Paul Irish의 블로그에 있는 다음 예는 다음과 같습니다.

var quack = someObject.quack;

if (typeof quack == "function" && quck.length == arguLength)
{
    // This thing can quack
}
동시에 오리 펀치 모드를 되돌릴 수도 있지만 이는 다음과 같습니다.

/**
    我们都知道jQuery的`$.css`方法可以通过使用颜色的名称给元素进行颜色赋值。
    但jQuery内置的颜色并非是那么丰富,如果我们想添加我们自定义的颜色名称应该怎么办?比如我们想添加`Burnt Sienna`这个颜色
*/

(function($){
    
    // 把原方法暂存起来:
    var _oldcss = $.fn.css;

    // 重写原方法:
    $.fn.css = function(prop,value){

        // 把自定义的颜色写进分支判断里,特殊情况特殊处理
        if (/^background-?color$/i.test(prop) && value.toLowerCase() === 'burnt sienna') {
           return _oldcss.call(this,prop,'#EA7E5D');

        // 一般情况一般处理,调用原方法
        } else {
           return _oldcss.apply(this,arguments);
        }
    };
})(jQuery);

// 使用方法:
jQuery(document.body).css('backgroundColor','burnt sienna')

하지만 문제가 있습니다. 이: 원래 방법을 수정해야 합니다. 이는 확장을 위해 열려야 하고 수정을 위해 닫혀야 한다는 '개방-폐쇄' 원칙을 위반하는 것입니다. 이 문제를 해결하는 방법? AOP 프로그래밍을 사용하십시오.

AOP

시작하기

AOP는 Aspect 지향 프로그래밍을 의미하며 이는 분명히 객체 지향 프로그래밍과 관련이 있습니다. Aspect는 "aspect" 또는 "side"로 번역될 수 있으므로 AOP는 관점 지향 프로그래밍입니다.

측면을 어떻게 이해하나요?

객체 지향 프로그래밍에서 우리가 정의하는 클래스는 일반적으로 도메인 모델이며, 해당 클래스가 갖는 메서드는 일반적으로 순수한 비즈니스 로직과 관련됩니다. 예:

(function($){

    var _old = $.fn.method;

    $.fn.method = function(arg1,arg2){

        if ( ... condition ... ) {
           return  ....
        } else {           // do the default
           return _old.apply(this,arguments);
        }
    };
})(jQuery);

그러나 일반적으로 실제 상황은 더 복잡합니다. 예를 들어 결제 방법에 승인 감지를 추가하거나 통계를 위한 로그 또는 내결함성 코드를 보내야 합니다. 그러면 코드는 다음과 같이 됩니다.

Class Person
{
    private int money;
    public void pay(int price)
    {
         this.money = this.money - price;   
    }
}

더 무서운 점은 비슷한 코드를 다른 메소드에도 추가해야 하기 때문에 코드의 유지보수성과 가독성이 큰 문제가 된다는 것입니다. 이렇게 분산되어 있지만 공통적으로 사용되는 비업무용 코드를 모아 좀 더 친근하게 사용하고 관리할 수 있기를 바랍니다. 이것이 바로 Aspect 프로그래밍입니다. 측면 프로그래밍은 원격 코드 수정 방지를 기반으로 코드 재사용을 달성합니다. 서로 다른 사물을 수평으로 자르고 내부 방식의 변형에 집중하는 것과 같습니다. 객체 지향 프로그래밍은 전반적인 아키텍처 설계에 더 많은 관심을 기울입니다.

구현

이전 섹션에서 소개한 덕펀치는 애스펙트 프로그래밍과 유사하며, 둘 다 원래 메서드의 기능을 보장하면서 변환합니다. 그러나 마지막에 언급했듯이 원래 방법을 직접 수정하는 패턴은 객체 지향 모범 사례의 원칙에 어긋납니다.

Javascript는 데코레이터 패턴(원본 객체에 추가 책임을 추가하지만 원본 객체 수정은 피함)을 사용하여 AOP 프로그래밍을 구현할 수 있습니다. 여기서 강조하고 싶은 것은 측면 프로그래밍은 단지 아이디어일 뿐이며 데코레이터 패턴은 이 아이디어를 실행하는 수단일 뿐이라는 것입니다. 예를 들어 Java에서는 프록시 패턴 등을 사용할 수 있습니다. . Aspect 프로그래밍은 Java에서 더 많은 여지가 있고 더 표준적입니다. 이 기사에서는 Java의 구현 모델을 소개하고 싶었지만 Java 수준이 제한되어 있고 Java의 구현을 잘 이해하지 못합니다. 여기에는 Javascript 구현만 표시됩니다.

  AOP中有一些概念需要介绍一下,虽然我们不一定要严格执行

  • joint-point:原业务方法;

  • advice:拦截方式

  • point-cut:拦截方法

  关于这三个概念我们可以串起来可以这么理解:

  当我们使用AOP改造一个原业务方法(joint-point)时,比如加入日志发送功能(point-cut),我们要考虑在什么情况下(advice)发送日志,是在业务方法触发之前还是之后;还是在抛出异常的时候,还是由日志发送是否成功再决定是否执行业务方法。

  比如gihub上的meld这个开源项目,就是一个很典型的AOP类库,我们看看它的API:

// 假设我们有一个对象myObject, 并且该对象有一个doSomething方法:

var myObject = {
    doSomething: function(a, b) {
        return a + b;
    }
};

// 现在我们想拓展它,在执行那个方法之后打印出刚刚执行的结果:

var remover = meld.after(myObject, 'doSomething', function(result) {
    console.log('myObject.doSomething returned: ' + result);
});

// 试试执行看:

myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3"

// 这个时候我们想移除刚刚的修改:

remover.remove();

  由此可以看出,AOP接口通常需要三个参数,被修改的对象,被修改对象的方法(joint-point),以及触发的时机(apce),还有触发的动作(point-cut)。上面说了那么多的概念,现在可能要让各位失望了,Javascript的实现原理其实非常简单

function doAfter(target, method, afterFunc){
    var func = target[method];
    return function(){
        var res = func.apply(this, arguments);
        afterFunc.apply(this, arguments);
        return res;   
    };
}

  当然,如果想看到更完备的解决方案和代码可以参考上面所说的meld项目

 结束语

  这一篇一定让你失望了,代码简单又寥寥无几。本篇主要在于介绍有关Javascript의 AOP 프로그래밍에 대해 이야기和AOP的这几类思想,我想编程的乐趣不仅仅在于落实在编码上,更在于整个架构的设计。提高代码的可维护性和可拓展性会比高深莫测的代码更重要。

 以上就是聊Javascript中的AOP编程的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.