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

前書き
ボブおじさんは、オブジェクト指向プログラミングをより適切に実装するために 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 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 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 までご連絡ください。
    JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

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

    ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

    現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

    next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

    私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

    next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

    この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

    JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

    JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

    JavaScriptの進化:現在の傾向と将来の見通しJavaScriptの進化:現在の傾向と将来の見通しApr 10, 2025 am 09:33 AM

    JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

    javascriptの分解:それが何をするのか、なぜそれが重要なのかjavascriptの分解:それが何をするのか、なぜそれが重要なのかApr 09, 2025 am 12:07 AM

    JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

    pythonまたはjavascriptの方がいいですか?pythonまたはjavascriptの方がいいですか?Apr 06, 2025 am 12:14 AM

    Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。

    See all articles

    ホット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衣類リムーバー

    AI Hentai Generator

    AI Hentai Generator

    AIヘンタイを無料で生成します。

    ホットツール

    mPDF

    mPDF

    mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

    WebStorm Mac版

    WebStorm Mac版

    便利なJavaScript開発ツール

    VSCode Windows 64 ビットのダウンロード

    VSCode Windows 64 ビットのダウンロード

    Microsoft によって発売された無料で強力な IDE エディター

    EditPlus 中国語クラック版

    EditPlus 中国語クラック版

    サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

    MantisBT

    MantisBT

    Mantis は、製品の欠陥追跡を支援するために設計された、導入が簡単な Web ベースの欠陥追跡ツールです。 PHP、MySQL、Web サーバーが必要です。デモおよびホスティング サービスをチェックしてください。