アラート(名前);
getAge:function(){
アラート(年齢);
}
}
}
return{
isInstance:function(){
if(uniqueInstance == null){
uniqueInstance =constructor();
}
return uniqueInstance;
}
})();
ioldfish.isInstance().getName();
上記の構造は明らかにパブリックかつプライベートです。プライベート変数 uniqueInstance (クラスがインスタンス化されているかどうかを識別します) とプライベート メソッド コンストラクターはパブリック メソッド isInstance (プライベート メソッド コンストラクターで定義されたメソッドを呼び出すことができます) を返します。 ioldfish .isInstance().getName(); まず isInstance() メソッドを通じてインスタンス化されているかどうかを確認し、次に getName() メソッドを通じてクロージャ内のプライベート変数名を取得します。このモードにはまだ多くのアプリケーション シナリオがありますが、すべてのユーザーがそれを使用できるわけではなく、ページに読み込む必要がある大きなカレンダー コントロールに遭遇したことはありませんか?それは...
JavaScript デザイン パターン ファクトリ モード ファクトリ
ファクトリ モード ファクトリ: 最初に抽象クラスを作成し、次にこの抽象クラスに基づいてサブクラスを派生し、サブクラス内にインスタンス化を延期するファクトリ メソッドを作成します。正直に言うと、JavaScript でのファクトリ パターンの適用は少し突飛です。結局のところ、JavaScript には Java のようなハードコーディングによる困難はありません。パターンがあるからパターンを避ける。
極端な例として、タブ切り替えやドロップダウン リストなどのコンポーネントに位置決め、フェーディング、遅延、その他の効果を追加します。まず、これらのコンポーネントのインターフェイスを定義します。
var Iwidget = new Interface("iwidget. ",[["addEffect"]]);
後続の派生サブクラスがそれを継承できるように、このインターフェイスを定義します。インターフェイスは addEffect メソッドを定義します。インターフェイス メソッドが実装された後、呼び出し元の学生は次のことに注意を払う必要はありません。各サブクラスの addEffect メソッドのコード実装。
var Widget = function(){}; Widget.prototype={ fire:function(model){ var widget = this.createWidget(model); //一部の生徒は、サブクラスがインターフェイス メソッドを定義する必要がある理由を尋ねました。 widget.addEffect(); return widget; show:function(){ //コード実装を表示 }, hide: function( ){ //コード固有の実装を隠す }, createWidget:function(model){ alert('抽象クラス、インスタンス化できません') } } ;
上記の例では、まず、派生サブクラスの親クラスとして抽象クラス Widget を定義します。どちらのタイプのコンポーネントにもコンテナーの表示と非表示が含まれることを考慮すると、これは親クラスで事前定義されています。サブクラス継承のメソッドを表示および非表示にします。
var xTab = function(){}; extend(xTab,Widget); xTab.prototype.createWidget = function(model){ var ウィジェット; case 'position': ウィジェット= 新しい xTabPosition (); ケース 'anim': ウィジェット = 新しい xTabAnim(); ケース '遅延': ウィジェット = new xTabDelay(); } }; extend(dropDown,Widget) = function(model) ){ var ウィジェット; switch(model){ case 'position': widget = newdropDownPosition(); case 'anim': ウィジェット = 新しいドロップダウンアニメーション (); ブレイク; デフォルト: ウィジェット = 新しいドロップダウン遅延 () サブクラス xTab と DropDown は、親クラスを継承し、createWidget メソッドを書き換えます。これらのインスタンスを作成するクラスがインターフェイスで合意された addEffect メソッドを実装している限り、異なるサブクラスは、配置、フェーディング、および遅延効果に応じて異なるインスタンスを作成します。 , メソッドコードの実装方法に関してはどれも同じなので、お好みに合わせて調整してください。 コードをコピー コードは次のとおりです。
var xTabPosition = function(){};
xTabPosition.prototype ={
}
}; ');
同様に、これらのエフェクトをバブル コンポーネントに追加する必要がある場合は、同じパターンに従うだけで、この設計パターンによりクラス間の結合が大幅に軽減され、さまざまな補助アクションを実装できることがわかります。特定の対話要件に従っていますが、コード実装の複雑さも必然的に増加します。結局のところ、このモードは Java とは異なり、クラス名をハードコーディングすることが目的ではありません。彼のデザインのアイデアを学んでください。したがって、上記の例は参考用です。大人がそばにいない限り、お子様は真似しないでください。
JavaScript 愛好家にとって、より価値のあるものは、ファクトリ パターンで言及されている「キャッシュ (メモ化) メカニズム」であるはずです。この本では、この機能を説明するために XHR オブジェクトを作成する例が示されていますが、その効果は明らかに十分ではありません。明らかに...
メモ化名詞の説明: 関数の各実行の結果をキーと値のペアに入れます (状況に応じて配列も使用できます)。後続の実行では、キーが値であるかどうかを確認します。値のペアがすでに存在する場合は、その値が返されます。存在しない場合は、関数本体の評価部分が実際に実行されます。明らかに、特にキーと値のペアでの値の検索は、関数の実行よりもはるかに高速です。
メモ化の威力は、再帰呼び出し中により効果的に発揮されます。以下は古典的なフィボナッチ数列です。 fib(20) は fib メソッドを 21891 回実行します。これが fib(40) の場合、これは 331160281 回実行されます。
function fib(n) { if (n < 2) { return n; return fib(n - 1) fib(n - 2) 見てみましょう再度使用する方法 メモ化を実装するには:
var iterMemoFib = (function() {
var queue = [1, 1]; var fib = function(n) { if (n >=cache.length) { //再帰を for (var i =cache.length; i <= n; i ) { cache[i] =cache[i - 2] cache[i - 1]; に変換します。 } } return queue[n-1]; } return fib; })(); memoize を使用して関数プロトタイプを拡張しますもちろん、頻繁に実行されない一部の関数については、キャッシュする必要がないため、このメソッドを使用する必要があります。
。
コードをコピー
コードは次のとおりです: Function.prototype.memoize = function() {
var Pad = {} ;
var self = this; var obj = argument .length > 0 ? argument[i] : null; var memoizedFn = function() { // パラメータを配列として保存します var args = []; for (var i = 0; i < argument.length; i ) { args[i] = 引数[i]; if (!(パッドの引数)) { パッド[引数] = self.apply(obj, 引数); リターンパッド[ args]; } memoizedFn.unmemoize = function() { return self; } return memoizedFn; } Function.prototype.unmemoize = function() { alert("メモ化されていない関数をメモ化解除しようとしています。"); return null; 使用法: fib.memoize(); Javascript デザイン パターン 合成モード: このデザイン パターンを使用してオブジェクトを結合します。プロパティとメソッドを追加し、リーフ オブジェクトを再帰的にバッチ処理して、結合されたオブジェクトのプロパティとメソッドを取得します。たとえば、銀行の種類ごとにオンライン バンキングとカートゥーン バンキングに分けて、表示するかどうかを設定できる銀行リストを動的に作成したいと考えています。組み合わせモードを使用してこれを実現するにはどうすればよいですか? 最初のステップは、最初にインターフェイスを定義することです。特定の種類のバンクまたは特定のバンクを表示できるかどうかを設定可能にするために、最初に 2 つのインターフェイス、showBank と HideBank について合意する必要があります。 var IcardItem = new Interface("icardItem",[["showBank"],["hideBank"]]); 次に、カードの組み合わせオブジェクトを定義し、カードの基本メソッド add、remove を設定します。組み合わせオブジェクト getChild は、このクラスが IcardItem インターフェイス クラスを継承しているため、2 つのインターフェイス メソッド showBank と HideBank も定義します。
コードをコピー
コードは次のとおりです:
var CardMain = function(id){ this.cards = []; this.element = document.createElement("div"); this.element.id = id; Interface.regImplement(this,IcardItem); }; cardMain.prototype = { add:function(card){ this.cards.push(card); this.element.appendChild(card.getElement()); }, remove:function(card){ for(i=0;len=this.cards.length,iif(cards[i] == Card){ this.cards.splice(i,1); 休憩; } this.element.removeChild(card.getElement()); } }, getChild:function(i){ return this.cards[i]; }, getElement:function(){ return this.element; }, showBank:function(){ this.element.style.display ="ブロック"; for(i=0;len=this.cards.length,ithis.cards[i].showBank(); } }, hideBank:function(){ this.element.style.display ="none"; for(i=0;len=this.cards.length,ithis.cards[i].hideBank(); } } };
その後、义叶子对オブジェクト类bankLogo を创建银行ロゴ、这里银行ロゴ都以带クラスのa标签标识:
varbankLogo = function(bankClassName){ this.element = document.createElement("a"); this.element.className = 銀行クラス名; Interface.regImplement(this,IcardItem); }; bankLogo.prototype ={ showBank:function(){ this.element.style.display ="block"; }, hideBank:function(){ this.element.style.display ="none"; }, getElement:function(){ return this.element; } };
最後に 1 つの本体オブジェクトを設定し、操作実行の関連情報を 1 つのモデムを形成します。方便调用:
var BankAction ={ bankList:[], addBank:function(card){ this.bankList.push(card) ; }, innerBank:function(conId){ for(i=0;len=this.bankList.length,ivar CardObj =this.bankList[i ].getElement(); } document.getElementById(conId).appendChild(cardObj); } };
が完了し、すべてのパッケージを含む最外層コンテナを生成する例を示します。その後、パッケージの種類に基づいて、放置行パッケージとスルーパッケージのコンテナをそれぞれ生成し、最後に各パッケージを生成します。例、并按层级关系形成 DOM 構造:
varbankDivT = new cardMain("PayCard");//创建最外层容器 var ebankCard = new cardMain("ebankCard");//创建网银类银行卡容器 var ktCard = new cardMain("ktCard" );//创建招行银行卡容器 var ccbBank = new BankLogo('Ebank-CMB');//创建招行银行卡 var abcBank = new BankLogo('Ebank-ABC');//创建卡通农行卡 var abcKtBank = new BankLogo('Kt-ABC');//创建卡通农行卡 ebankCard.add(ccbBank); ebankCard.add(abcBank); ktCard.add(abcKtBank); bankDivT.add(ebankCard); bankDivT.add(ktCard); BankAction.addBank(bankDivT); BankAction.innerBank("bankList");
自動生成の银列表、DOM 構造の例:
組み合わせモード アプリケーションは、ユーザー インターフェイスを動的に生成する場合に非常に適した選択肢であり、まとまりのあるコードを大幅に簡素化し、保守性を向上させることができます。ただし、リーフ オブジェクトが多数ある場合、再帰には依然としてパフォーマンスの問題が発生するため、使用には注意が必要です。
JavaScript デザイン パターンのデコレータ パターン
デコレータ パターン: 新しいサブクラスを作成せずに、オブジェクトの新しい関数を作成できます。例: Alipay チェックアウト赤い封筒と残高支払いを組み合わせたアプリケーション シナリオ。
var Ieconomics = new Interface("ieconomics",[["getPrice"]]);
まずコンポーネントクラスを作成し、コンポーネントに基づいてインスタンス化されたオブジェクトがパラメータとしてデコレータクラスに渡されます。これにより、デコレータはコンポーネント内のさまざまなメソッドを呼び出すことができます。
varconomic = function(){ Interface.regImplement(this,Ieconomics); economic.prototype={ //コード実装 }; > 次に、派生デコレーター オプション クラスの親クラスとしてデコレーター抽象クラスを作成します。
コードをコピー
最後に、上記に基づいて抽象クラス、派生 デコレータ オプション クラスを作成します:
コードをコピー コードは次のとおりです: //赤い封筒の装飾またはオプションクラス
var Coupon = function(economic){
//抽象クラスで装飾されたコンストラクターを呼び出します
economicsDecorator.call(this,economic)
//赤い封筒の合計価格を取得する具体的な実装
} }; myCoupon = new Economy(); myCoupon = new Coupon(myCoupon); 最初にコンポーネント myCoupon のインスタンスを作成し、それを渡すのは非常に簡単です。オブジェクトをデコレータ オプション クラス クーポンへのパラメータとして使用します。コードの両方の行で変数 myCoupon に値を割り当てていることがわかります。これは、どちらも同じインターフェイス クラスを実装しており、互換的に使用できるためです。 これを見た注意深い学生は、クーポン クラスに getCoupon メソッドが追加されていることに気づくかもしれません。現時点では問題ありませんが、引き続きショッピング クーポン デコレータ オプション クラスを作成し、red を使用してみてはいかがでしょうか。封筒も一緒に? コードをコピー コードは次のとおりです: //Shopping Voucher Decorator Option Class varバウチャー = function(economic){
economicsDecorator.call(this,economic)
extend(voucher,couponDecorator){
getPrice :function(){
return this.getPrice() - this.getVoucher();
ここ このシナリオの getCoupon メソッドが見つかりません。これは、伝票が myCoupon を装飾するときに、その親クラスの EconomysDecorator に getCoupon メソッドが含まれていないため、当然取得できません。
デコレータ抽象クラスconomicsDecoratorを分析し、パラメータとしてmyCouponへの参照を渡します。このパラメータを使用して、いくつかの小さなアクションを実行し、新しく追加されたメソッドを取得できます。
コードをコピー
コードは次のとおりです。
varconomicsDecorator = function(economic){ this.economic = electric; this.interface = Ieconomics; for(var k in this.economic){ if( typeof this.economic[key] !== "function"){ continue; var i; for(i = 0;len = this.interface.methods.length,i //このメソッドがインターフェイス クラスに含まれているかどうかをトラバースして比較し、含まれている場合は次のメソッドを返します if(key == this.interface.methods[i][0] ) { break ; } } if(i vardecorator = this;匿名関数を使用して新しいメソッドを呼び出します (function(methodName) { decorator[methodName] = function() { returndecorator.economic[methodName](); }; }) (キー); } } this.regImplement(economic,Ieconomics); economicsDecorator.prototype={ getPrice:function(){ return this.economic.getPrice(); } }; 上記のコードを見ると、デコレータ抽象クラスにいくつかの変更が加えられています。新しいメソッドがオプション クラスで定義されると、それをデコレータ抽象クラスで動的に定義できるようにするためです。ここでは、デコレータ パターンを使用するためのアイデアを示します。具体的な実装コードは、まだ開発中であるため、Alipay のレジの新しいバージョンがリリースされた後に共有します。詳細なデザインをあなたと一緒に作ります。 JavaScript デザイン パターンのブリッジ モード ブリッジ モード: 抽象化とその実装を分離し、独立して変更できるようにします。実際、これは非常に簡単で、API と特定のイベントの間にブリッジを追加するだけで、API とそれを使用するクラスおよびオブジェクトの間の結合が軽減されます。
実際、ブリッジ モードはほとんどの学生にとって馴染みのないものではありません。次の this.getName は、内部のプライベート変数にアクセスすることによって実現されるブリッジ メソッドです。外部と内部のコミュニケーションの橋渡しをします。
コードをコピー
コードは次のとおりです。 var ioldfish = function(){ var name = 'Old Fish';
this.getName = function(){
alert(name); } 最も一般的に使用されるブリッジモードはイベントリスナーのコールバック関数です。ユーザー情報を取得する API インターフェース関数は次のとおりです。 コードをコピー
コードは次のとおりです:
次に行う必要があるのは、この API とイベントのトリガーとの間のブリッジ関係を確立することです addEvent(element,'click',bridgeMethod); function BridgeMethod(e) { getUserInfo(this.userid,function(){ //コールバック関数の実装コード }); } 要素がクリックされたオブジェクトは getIserInfo ではありませんが、新しいブリッジ メソッド、bridgeMethod が作成されます。このブリッジング層を通じて、API インターフェイス関数とクリック イベントが比較的独立しているため、API の適用範囲が大幅に広がります。
JavaScript デザイン パターン アダプター パターン
アダプター パターン: たとえば、以前はプロトタイプ フレームワークを使用していましたが、現在は 2 つのフレームワーク間で移行する方法を計画しています。
、たとえば、プロトタイプの $ メソッドを YUI の get メソッドに変換する方法:
コードをコピー
コードは次のとおりです:
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
2024-10-22 09:46:29
2024-10-13 13:53:41
2024-10-12 12:15:51
2024-10-11 22:47:31
2024-10-11 19:36:51
2024-10-11 15:50:41
2024-10-11 15:07:41
2024-10-11 14:21:21
2024-10-11 12:59:11
2024-10-11 12:17:31