まずはAOPプログラミングの話はやめて、アヒルパンチプログラミングから始めましょう。
ウィキペディアでアヒルパンチを検索すると、モンキーパッチという項目が見つかるはずです。説明によると、モンキーパッチという言葉は、作戦中にひそかにコードを変更するという意味のゲリラパッチに由来しており、ゲリラという言葉はゴリラと同じ発音で、後者は猿に似た意味(前者は「ゴリラ」の意味)、とのこと。ついにフォーモンキーパッチに進化しました。
ダックパンチについて聞いたことがない人は、ダックタイピングについて聞いたことがあるかもしれません。よくある例を挙げると、アヒルの見分け方です:
When I see a Bird that walks like a Javascript での AOP プログラミングについて話す and swim like a Javascript での AOP プログラミングについて話す and quacks like a Javascript での AOP プログラミングについて話す, I call that Bird a Javascript での AOP プログラミングについて話す.
もしそうなら、アヒルのように鳴き、アヒルのように泳ぐ動物がいることを発見しました。それはアヒルです。
このテストは少し明白で無意味に思えるかもしれませんが、非常に実用的です。 そして、それはプログラミングにおけるある種の問題、つまり Javascript または同様の動的言語の場合、「インターフェイス」または「基本クラス」をどのように実装するかという問題を解決するために使用できます。それらの過去についてはまったく気にする必要はありません。メソッドの型やパラメーターが、それらを使用するときに必要なものであるかどうかだけを気にします。
var quack = someObject.quack; if (typeof quack == "function" && quck.length == arguLength) { // This thing can quack }
実際、私が表現したいのは、次のとおりです。このアヒルパンチは実際にはアヒルのタイピングから派生したものです:
アヒルのように歩き、アヒルのように話すなら、それはアヒルですよね? ve got to justPunch that Javascript での AOP プログラミングについて話す until it returns what you Expect.
アヒルにロバの鳴き声を出させたい場合はどうすればいいですか? ロバの鳴き声が出るまで殴ってください... これは非常に鮮やかなことを思い出させます。ジョーク:
テスト用 米国、香港、中国本土の警察の力に基づいて、国連は3つの森林に3匹のウサギを置き、3人の警察官のうち誰が最初にウサギを見つけられるかを確認しました。タスク: ウサギを見つけてください。 (中略…) 最後に、ある国の警察官は4人だけで一日麻雀をしていましたが、夕方になるとそれぞれが警棒を持って森に入って行きました、5分も経たないうちに叫び声が聞こえてきました。森から動物たちがやって来て、彼はタバコを吸いながら話したり笑ったりしながら出てきた、そして彼の後ろには鼻を打撲して顔が腫れ上がったクマがいて、「もう戦わないでください、私はただの人間です」と言いました。ウサギ…」
アヒルパンチは少し激しいですが、それでも良いものです。効果的な方法です。コードの実装とは、元のコードに必要な機能を適合させることを意味します。たとえば、Paul Irish のブログにあるこの例:
/** 我们都知道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')
同時に、アヒルパンチ モードを逆にすることもできますが、次のようになります:
(function($){ var _old = $.fn.method; $.fn.method = function(arg1,arg2){ if ( ... condition ... ) { return .... } else { // do the default return _old.apply(this,arguments); } }; })(jQuery);
しかし、これには問題があります。元のメソッドは次のようにする必要があります。変更されました。これは、拡張にはオープン、変更にはクローズする必要がある「オープン-クローズ」原則に違反します。この問題を解決するにはどうすればよいでしょうか? AOP プログラミングを使用します。
AOPはアスペクト指向プログラミングの略で、明らかにオブジェクト指向プログラミングに関連しています。アスペクトは「側面」または「側面」と翻訳できるため、AOP はアスペクト指向プログラミングです。
スライスってどうやって理解していますか?
オブジェクト指向プログラミングでは、定義するクラスは通常ドメインモデルであり、クラスが持つメソッドは通常、純粋なビジネスロジックに関連しています。例:
Class Person { private int money; public void pay(int price) { this.money = this.money - price; } }
しかし、通常、実際の状況はより複雑です。たとえば、支払い方法に認証検出を追加したり、統計用のログを送信したり、フォールトトレラントなコードを送信したりする必要があります。コードは次のようになります:
Class Person { private int money public void pay(price) { try { if (checkAuthorize() == true) { this.money = this.money - price; sendLog(); } } catch (Exception e) { } } }
さらに恐ろしいのは、他のメソッドにも同様のコードを追加する必要があるため、コードの保守性と可読性が大きな問題になることです。私たちは、これらの散在しているが一般的な非ビジネス コードを収集し、それらをよりフレンドリーに使用および管理したいと考えています。これがアスペクト プログラミングです。アスペクト プログラミングは、リモート コードの変更を回避することに基づいてコードの再利用を実現します。さまざまなオブジェクトを水平方向に切り取り、内部メソッドの変換に焦点を当てるようなものです。オブジェクト指向プログラミングでは、全体的なアーキテクチャ設計により多くの注意が払われます。
前のセクションで紹介したダックパンチはアスペクトプログラミングに似ており、どちらも元のメソッドを変換しながらその機能を保証します。ただし、最後に述べたように、元のメソッドを直接変更するパターンは、オブジェクト指向のベスト プラクティスの原則に反します。
JavaScript は、デコレーター パターン (元のオブジェクトに追加の責任を追加しますが、元のオブジェクトの変更は回避します) を使用して、AOP プログラミングを実装できます。ここで強調したいのは実装であることに注意してください。アスペクト プログラミングは単なるアイデアであり、デコレータ パターンはこのアイデアを実践するための単なる手段であるということです。たとえば、Java ではプロキシ パターンなどが使用できます。 。アスペクト プログラミングは 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)!