ホームページ ウェブフロントエンド jsチュートリアル JavaScriptを深く理解するシリーズ(6):単一責任S.O.L.I.Dの5原則のSRP_javascriptスキル

JavaScriptを深く理解するシリーズ(6):単一責任S.O.L.I.Dの5原則のSRP_javascriptスキル

May 16, 2016 pm 05:57 PM

前書き
ボブおじさんは、オブジェクト指向プログラミングをより適切に実装するために S.O.L.I.D の 5 つの原則を提案し、継承しました。 5 つの原則は次のとおりです。

単一責任原則 (単一責任 SRP)
オープン/クローズド。原則 (OCP)
リスコフ置換原則 (LSP)
インターフェース分離原則 (ISP)
依存性反転原則 (DIP)
5 つの原則はブログ コミュニティで議論されてきたと思います。特に C# の実装については、プロトタイプベースの動的型言語である JavaScript と比べるとまだ少ないため、このシリーズでは JavaScript プログラミング言語に基づいた 5 つの原則の適用について説明します。 OK、最初の記事「単一責任」を始めましょう。

英語原文: http://freshbrewedcode.com/derekgreer/2011/12/08/solid-javascript-single-responsibility-principle/

単一責任
単一の説明責任は次のとおりです:

クラスを変更する理由は 1 つだけである必要があります
クラスを変更する理由は 1 つだけである必要があります
コードをコピー
クラス (JavaScript ではオブジェクトである必要があります)関連する動作は何を意味しますか?の近いセットが必要です。単一の責任に従うことの利点は、オブジェクトに多くの責任がカプセル化されている場合、1 つの責任を変更する必要があると、必然的にオブジェクトの他の責任のコードに影響を与えることになります。切り離すことで、責任ある各従業員がより柔軟に変更できるようになります。

しかし、オブジェクトの複数の動作が複数の責任を構成するのか、それとも 1 つの責任を構成するのかをどのようにして知るのでしょうか?書籍『オブジェクト デザイン: 役割、責任、およびコラボレーション』で提案されている役割ステレオタイプの概念を参照して決定できます。この概念では、責任を区別するために次の役割ステレオタイプが提案されています。

情報保持者 – このオブジェクトは保存するように設計されています。オブジェクトを作成し、オブジェクト情報を他のオブジェクトに提供します。
Structurer - このオブジェクトは、オブジェクトと情報の間の関係を維持するように設計されています。
Service Provider - このオブジェクトは、作業を処理し、他のオブジェクトにサービスを提供するように設計されています。
Controller - このオブジェクトは、一連のオブジェクトを制御するように設計されています。責任ある決定 タスク処理
コーディネーター - このオブジェクトは意思決定の処理作業を行わず、単に他のオブジェクトに作業を委任するだけです
インターフェイス - このオブジェクトは、システムのさまざまな部分で情報 (またはリクエスト) を変換するように設計されています
理解すると、これらの概念を使用すると、コードに複数の責任があるのか​​、それとも単一の責任があるのか​​を簡単に知ることができます。

コード例
このコード例は、ショッピング カートに商品を追加する方法を示しています。コードは次のとおりです。

コピーcode コードは次のとおりです。

function Product(id, description) {
this.getId = function () {
return id;
};
this.getDescription = function () {
return description;

function Cart(eventAggregator) {
var items = [ ];

this.addItem = function (item) {
items.push(item)
}

(function () {
var products = [新製品 (1, "スター・ウォーズ レゴ船"),
新製品 (2, "バービー人形"),
新製品 (3, "リモコン飛行機")],
カート = new Cart() ;

function addToCart() {
var productId = $(this).attr('id');
var product = $.grep(products, function ( x) {
return x.getId() == productId;
cart.addItem(product) = $(' ').html(product.getDescription()).attr('id-cart', product.getId()).appendTo("#cart"); >products.forEach(function (product) {
var newItem = $('
  • ').html(product.getDescription())
    .attr('id', product .getId())
    .dblclick(addToCart)
    .appendTo("#products")
    })();


    それぞれ 2 つの関数を宣言します。製品とカートの説明に使用されます。匿名関数の役割は、画面を更新してユーザーと対話することです。これはそれほど複雑な例ではありませんが、匿名関数には無関係な多くの役割が含まれています。見てみましょう。責任の数:

    まず、製品コレクションの宣言があります。
    次に、製品コレクションを #product 要素にバインドするコードがあり、イベント ハンドラーも追加します。ショッピングカートに追加するための
    3 番目に、Cart ショッピングカートを表示する機能があります
    4 番目に、商品アイテムをショッピングカートに追加して表示する機能があります
    コードのリファクタリング
    コードを独自のオブジェクトに格納できるように分解してみましょう。このために、Martinfowler のイベント アグリゲーター (Event Aggregator) 理論を参照して、オブジェクト間で通信するコードを処理します。
    まず、イベント集約関数を実装しましょう。この関数は 2 つの部分に分かれており、1 つはハンドラーのコールバック コードに使用され、もう 1 つはサブスクライブとパブリッシュに使用される EventAggregator です。イベント。コードは次のとおりです:




    コードをコピーします


    コードは次のとおりです:

    function Event(name) {
    var handlers = [];

    this.getName = function () {
    名前を返します。
    };

    this.addHandler = function (ハンドラー) {
    handlers.push(ハンドラー);
    };

    this.removeHandler = function (ハンドラー) {
    for (var i = 0; i < handlers.length; i ) {
    if (handlers[i] == ハンドラー) {
    handlers.splice(i, 1);
    休憩;
    }
    }
    };

    this.fire = function (eventArgs) {
    handlers.forEach(function (h) {
    h(eventArgs);
    });
    };
    }

    function EventAggregator() {
    var events = [];

    function getEvent(eventName) {
    return $.grep(events, function (event) {
    return event.getName() === イベント名;
    })[0];
    }

    this.publish = function (eventName,eventArgs) {
    var events = getEvent(eventName);

    if (!event) {
    event = new Event(eventName);
    events.push(イベント);
    }
    event.fire(eventArgs);
    };

    this.subscribe = function (eventName, handler) {
    var events = getEvent(eventName);

    if (!event) {
    event = new Event(eventName);
    events.push(イベント);
    }

    event.addHandler(ハンドラー);
    };
    }

    その後、我们来註製品对象、代码如下:
    复制代記入代码如下:

    function Product(id, description) {
    this.getId = function () {
    return id;
    };
    this.getDescription = function () {
    説明を返します;
    };
    }

    次に、Cart オブジェクト、このオブジェクトの addItem の関数を参照して、イベント itemAdded を配布し、その後 item をパラメータとして削除します。 >
    复制代码代码如下: function Cart(eventAggregator) {
    var items = [];

    this.addItem = function (item) {
    items.push(item);
    eventAggregator.publish("itemAdded", item);
    };
    }


    CartController は主にカート オブジェクトとイベント コマータを受け取り、阅itemAdded によって要素ポイントを追加し、productSelected イベントによって製品を追加します。 >
    复制代码

    代码如下: function CartController(cart,eventAggregator) { eventAggregator.subscribe("itemAdded", function (eventArgs) { var newItem = $('
  • ').html(eventArgs.getDescription()).attr('id-cart',eventArgs.getId()).appendTo ("#カート")
    });
    eventAggregator.subscribe("productSelected", function (eventArgs) {
    cart.addItem(eventArgs.product);
    });
    }


    リポジトリの目的は、データを取得し (ajax から取得できる)、その後 getdata を公開する方法です。复制代码


    代码如下:

    function ProductRepository() {
    var products = [new Product(1, "Star Wars Lego Ship"),
    新製品(2、「バービー人形」)、新製品(3、「リモコン飛行機」)]; this.getProducts = function () { 商品を返品する; } }

    ProductController では、onProductSelect メソッドの 1 つが定義されており、主に配布触発productSelected イベントです。forEach は主にデータを商品リストに固定するために使用されます。 >



    复制代码


    代码如下:

    function ProductController(eventAggregator, productRepository) {
    var products = productRepository.getProducts();
    function onProductSelected() { var productId = $(this).attr('id'); var product = $.grep(products, function (x) { return x.getId() == productId; })[0]; eventAggregator.publish("productSelected", { 製品: 製品
    });
    }

    products.forEach(function (product) {
    var newItem = $('
  • ').html(product.getDescription())
    .attr('id', product.getId())
    .dblclick(onProductSelected)
    .appendTo("#products")
    });
    }


    最後の安全関数:




    复制代码


    代码如下:

    (function () {
    var eventsAggregator = new EventAggregator(),
    cart = new Cart(eventAggregator),
    cartController = new CartController(cart,eventAggregator),
    productRepository = new ProductRepository(),
    productController = new ProductController(eventAggregator, productRepository)
    })();

    匿名関数のコードが削減されていることがわかります。オブジェクトのインスタンス化コード。このコードでは、情報を受け取ってアクションに渡すコントローラーの概念を導入しました。また、主にオブジェクトの表示を処理するために使用されるリポジトリーの概念も導入しました。リファクタリングの結果、オブジェクト宣言をたくさん書くことになりますが、利点は、表示データを表示する必要があり、コレクションを処理するために処理コレクションを変更する必要があるため、それぞれのオブジェクトが明確な責任を持つことです。結合度は非常に低いです。

    最終コード
    コードをコピー コードは次のとおりです:

    関数イベント(名前) {
    var handlers = [];

    this.getName = function () {
    return name;

    this.addHandler = function (ハンドラー) {
    handlers.push(handler);
    };

    this.removeHandler = function (ハンドラー) {
    for (var i = 0; i < handlers.length ; i ) {
    if (handlers[i] == ハンドラー) {
    break;
    }
    }; >
    this.fire = function (eventArgs) {
    handlers.forEach(function (h) {
    h(eventArgs);
    }); >
    function EventAggregator() {
    var events = [];

    function getEvent(eventName) {
    return $.grep(events, function (event) {
    return event .getName( ) === イベント名;
    })[0];

    this.publish = function (eventName,eventArgs) {
    var イベント = getEvent(eventName);

    if (!event) {
    event = new Event(eventName);
    }
    event.fire(eventArgs); };

    this.subscribe = function (eventName, handler) {
    var イベント = getEvent(eventName);

    if (!event) {
    event = new Event(イベント名);
    events.push(イベント);

    event.addHandler(ハンドラー);
    }

    関数説明) {
    this.getId = function () {
    return id
    };
    return description; }

    function Cart(eventAggregator) {
    var items = [];

    this.addItem = function (item) {
    items.push(item); eventAggregator.publish ("itemAdded", item);
    };
    }

    function CartController(cart,eventAggregator) {
    eventAggregator.subscribe("itemAdded", function (eventArgs) {
    var newItem = $('
  • ').html(eventArgs.getDescription()).attr('id-cart',eventArgs.getId()).appendTo("#cart ");
    });

    eventAggregator.subscribe("productSelected", function (eventArgs) {
    cart.addItem(eventArgs.product);
    });
    }

    function ProductRepository() {
    var products = [新製品(1, "スター・ウォーズ レゴ船"),
    新製品(2, "バービー人形"),
    新製品(3, "リモコン飛行機")];

    this.getProducts = function () {
    商品を返品する;
    }
    }

    function ProductController(eventAggregator, productRepository) {
    var products = productRepository.getProducts();

    function onProductSelected() {
    var productId = $(this).attr('id'); $.grep (products, function (x) {
    return x.getId() == productId;
    })[0];
    eventAggregator.publish("productSelected", {
    product: product
    });
    }

    products.forEach(function (product) {
    var newItem = $('
  • ').html(product .getDescription( ))
    .attr('id', product.getId())
    .dblclick(onProductSelected)
    .appendTo("#products")
    ; }

    (function () {
    var eventsAggregator = new EventAggregator(),
    cart = new Cart(eventAggregator),
    cartController = new CartController(cart,eventAggregator),
    productRepository = new ProductRepository(),
    productController = new ProductController(eventAggregator, productRepository)
    })();


    概要
    このリファクタリングの結果を見て、一部のブロガーは次のように思うかもしれません。本当にそんなに複雑にする必要があるのですか?と私は尋ねました。私が言えるのは、これを行うべきかどうかはプロジェクトの状況次第だということだけです。

    プロジェクトが非常に小規模でコードの量がそれほど多くない場合、実際にはそれほど複雑にリファクタリングする必要はありませんが、プロジェクトが非常に複雑な大規模プロジェクトや小規模なプロジェクトの場合は、プロジェクトが将来的に急速に成長する可能性がある場合は、将来のメンテナンスを容易にするために、初期段階で責任を分離するための SRP 原則を考慮する必要があります。
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

    ホットAIツール

    Undresser.AI Undress

    Undresser.AI Undress

    リアルなヌード写真を作成する AI 搭載アプリ

    AI Clothes Remover

    AI Clothes Remover

    写真から衣服を削除するオンライン AI ツール。

    Undress AI Tool

    Undress AI Tool

    脱衣画像を無料で

    Clothoff.io

    Clothoff.io

    AI衣類リムーバー

    Video Face Swap

    Video Face Swap

    完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

    ホットツール

    メモ帳++7.3.1

    メモ帳++7.3.1

    使いやすく無料のコードエディター

    SublimeText3 中国語版

    SublimeText3 中国語版

    中国語版、とても使いやすい

    ゼンドスタジオ 13.0.1

    ゼンドスタジオ 13.0.1

    強力な PHP 統合開発環境

    ドリームウィーバー CS6

    ドリームウィーバー CS6

    ビジュアル Web 開発ツール

    SublimeText3 Mac版

    SublimeText3 Mac版

    神レベルのコード編集ソフト(SublimeText3)

    JavaScriptエンジン:実装の比較 JavaScriptエンジン:実装の比較 Apr 13, 2025 am 12:05 AM

    さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

    Python vs. JavaScript:学習曲線と使いやすさ Python vs. JavaScript:学習曲線と使いやすさ Apr 16, 2025 am 12:12 AM

    Pythonは、スムーズな学習曲線と簡潔な構文を備えた初心者により適しています。 JavaScriptは、急な学習曲線と柔軟な構文を備えたフロントエンド開発に適しています。 1。Python構文は直感的で、データサイエンスやバックエンド開発に適しています。 2。JavaScriptは柔軟で、フロントエンドおよびサーバー側のプログラミングで広く使用されています。

    C/CからJavaScriptへ:すべてがどのように機能するか C/CからJavaScriptへ:すべてがどのように機能するか Apr 14, 2025 am 12:05 AM

    C/CからJavaScriptへのシフトには、動的なタイピング、ゴミ収集、非同期プログラミングへの適応が必要です。 1)C/Cは、手動メモリ管理を必要とする静的に型付けられた言語であり、JavaScriptは動的に型付けされ、ごみ収集が自動的に処理されます。 2)C/Cはマシンコードにコンパイルする必要がありますが、JavaScriptは解釈言語です。 3)JavaScriptは、閉鎖、プロトタイプチェーン、約束などの概念を導入します。これにより、柔軟性と非同期プログラミング機能が向上します。

    JavaScriptとWeb:コア機能とユースケース JavaScriptとWeb:コア機能とユースケース Apr 18, 2025 am 12:19 AM

    Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。

    JavaScript in Action:実際の例とプロジェクト JavaScript in Action:実際の例とプロジェクト Apr 19, 2025 am 12:13 AM

    現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

    JavaScriptエンジンの理解:実装の詳細 JavaScriptエンジンの理解:実装の詳細 Apr 17, 2025 am 12:05 AM

    JavaScriptエンジンが内部的にどのように機能するかを理解することは、開発者にとってより効率的なコードの作成とパフォーマンスのボトルネックと最適化戦略の理解に役立つためです。 1)エンジンのワークフローには、3つの段階が含まれます。解析、コンパイル、実行。 2)実行プロセス中、エンジンはインラインキャッシュや非表示クラスなどの動的最適化を実行します。 3)ベストプラクティスには、グローバル変数の避け、ループの最適化、constとletsの使用、閉鎖の過度の使用の回避が含まれます。

    Python vs. JavaScript:コミュニティ、ライブラリ、リソース Python vs. JavaScript:コミュニティ、ライブラリ、リソース Apr 15, 2025 am 12:16 AM

    PythonとJavaScriptには、コミュニティ、ライブラリ、リソースの観点から、独自の利点と短所があります。 1)Pythonコミュニティはフレンドリーで初心者に適していますが、フロントエンドの開発リソースはJavaScriptほど豊富ではありません。 2)Pythonはデータサイエンスおよび機械学習ライブラリで強力ですが、JavaScriptはフロントエンド開発ライブラリとフレームワークで優れています。 3)どちらも豊富な学習リソースを持っていますが、Pythonは公式文書から始めるのに適していますが、JavaScriptはMDNWebDocsにより優れています。選択は、プロジェクトのニーズと個人的な関心に基づいている必要があります。

    Python vs. JavaScript:開発環境とツール Python vs. JavaScript:開発環境とツール Apr 26, 2025 am 12:09 AM

    開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

    See all articles