目次
このクラスは、コンストラクター内で抽象クラス UserQueue への依存関係を宣言します。つまり、依存関係はコンストラクター内で new を使用して操作されるのではなく、依存関係注入フレームワークまたはファクトリまたはビルダー パターンを使用して外部から注入されます。 " >UserProcessor 内のキューへの依存関係は、new 操作などのハードコードされたメソッドを通じてコン​​ストラクター内で直接インスタンス化することで取得できます。しかし、これは典型的なコード ハード プログラミングであり、クライアント クラスとその依存関係の間に強い結合が生じ、テスト容易性が大幅に低下します。 このクラスは、コンストラクター内で抽象クラス UserQueue への依存関係を宣言します。つまり、依存関係はコンストラクター内で new を使用して操作されるのではなく、依存関係注入フレームワークまたはファクトリまたはビルダー パターンを使用して外部から注入されます。
模板方法模式实现IOC" >模板方法模式实现IOC
ホームページ Java &#&チュートリアル IOC制御反転例の詳細説明

IOC制御反転例の詳細説明

Jul 21, 2017 pm 02:33 PM
違う コントロール デザインパターン

N Inversion of Control (英語の略語) は、フレームワークの重要な機能であり、オブジェクト指向プログラミングの特別な用語ではありません。これは、依存関係の注入 (DI) および依存関係の検索 (依存関係の検索) とは何の関係もありません。

Spring を使用したことのある開発者は皆、ioc 制御関数のことを知っています。

IOCを実装するための依存性注入

依存性注入はIOCの最も基本的な実装方法であり、最も一般的に使用されるオブジェクト指向設計方法の1つです。制御の反転効果を達成するために依存関係を挿入する方法、例から始めます:

public interface UserQueue {void add(User user);void remove(User user);

    User get();

}public abstract class AbstractUserQueue implements UserQueue {protected LinkedList<User> queue = new LinkedList<>();

    @Overridepublic void add(User user) {
        queue.addFirst(user);
    }

    @Overridepublic void remove(User user) {
        queue.remove(user);
    }

    @Overridepublic abstract User get();

}public class UserFifoQueue extends AbstractUserQueue {public User get() {return queue.getLast();
    }

}public class UserLifoQueue extends AbstractUserQueue {public User get() {return queue.getFirst();
    }

}
ログイン後にコピー
UserQueue このインターフェイスは、User オブジェクトをキューに格納するためのパブリック メソッドを定義します。 AbstractUserQueue は、後続の継承クラスにいくつかの共通メソッド実装を提供します。最後の UserFifoQueueUserLifoQueue は、それぞれ FIFO キューと LIFO キューを実装します。

UserQueue 接口定义了公共的方法,用于在一个队列中去存放User对象。AbstractUserQueue则是为后续的继承类,提供了一些公用的方法实现。最后的UserFifoQueue 和 UserLifoQueue,则是分别实现了FIFO 和 LIFO 队列。

这是实现子类多态性的一种有效方式。

通过创建一个依赖于UserQueue抽象类型(也称为DI术语中的服务)的客户端类,可以在运行时注入不同的实现,无需会重构使用客户端类的代码:

public class UserProcessor {private UserQueue userQueue;public UserProcessor(UserQueue userQueue) {this.userQueue = userQueue;
    }public void process() {// process queued users here    }

}
ログイン後にコピー

UserProcessor展示了依赖注入确实是IOC的一种方式。

我们可以通过一些硬编码方式 如 new 操作,直接在构造函数中实例化在UserProcessor中获取对队列的依赖关系。但这是典型的代码硬编程,它引入了客户端类与其依赖关系之间的强耦合,并大大降低了可测性。

该类在构造函数中声明对抽象类 UserQueue 的依赖。也就是说,依赖关系不再通过在构造函数中使用 new 操作, 相反,通过外部注入的方式,要么使用依赖注入框架,要么使用factory或builders模式。

使用依赖注入,客户端类的依赖关系的控制,不再位于这些类中;而是在注入器中进行,看如下代码:

public static void main(String[] args) {
     UserFifoQueue fifoQueue = new UserFifoQueue();
     fifoQueue.add(new User("user1"));
     fifoQueue.add(new User("user2"));
     fifoQueue.add(new User("user3"));
     UserProcessor userProcessor = new UserProcessor(fifoQueue);
     userProcessor.process();
}
ログイン後にコピー

上述方式达到了预期效果,而且对UserLifoQueue的注入也简单明了。これは、サブクラスのポリモーフィズムを実現する効果的な方法です。

UserQueue 抽象型 (DI 用語ではサービスとも呼ばれる) に依存するクライアント クラスを作成すると、クライアント クラスを使用するコードをリファクタリングすることなく、実行時にさまざまな実装を挿入できます。 code>UserProcessor は、依存関係の注入が実際に IOC の方法であることを示しています。

UserProcessor 内のキューへの依存関係は、new 操作などのハードコードされたメソッドを通じてコン​​ストラクター内で直接インスタンス化することで取得できます。しかし、これは典型的なコード ハード プログラミングであり、クライアント クラスとその依存関係の間に強い結合が生じ、テスト容易性が大幅に低下します。 このクラスは、コンストラクター内で抽象クラス UserQueue への依存関係を宣言します。つまり、依存関係はコンストラクター内で new を使用して操作されるのではなく、依存関係注入フレームワークまたはファクトリまたはビルダー パターンを使用して外部から注入されます。

依存関係注入を使用すると、クライアント クラスの依存関係の制御はこれらのクラスに配置されなくなり、代わりにインジェクター内で行われます。次のコードを参照してください:

public interface SubjectObserver {void update();

}
ログイン後にコピー
上記のメソッドは期待どおりの効果を実現します。 UserLifoQueue の挿入も単純明快です。

オブザーバー パターンは IOC を実装します

オブザーバー パターンを介して IOC を直接実装することも、一般的で直感的な方法です。大まかに言うと、IOC はオブザーバーを通じて実装されます。オブザーバー パターンは通常、モデル ビューのコンテキストでモデル オブジェクトの状態変化を追跡するために使用されます。

一般的な実装では、たとえば addObserver メソッドを呼び出すことによって、1 つ以上のオブザーバーが監視可能なオブジェクト (パターン用語ではサブジェクトとも呼ばれます) にバインドされます。オブザーバーとオブザーバーの間のバインディングが定義されると、オブザーバーの状態が変化すると、オブザーバーを呼び出す操作がトリガーされます。次の例を見てください。

public class User {private String name;private List<SubjectObserver> observers = new ArrayList<>();public User(String name) {this.name = name;
    }public void setName(String name) {this.name = name;
        notifyObservers();
    }public String getName() {return name;
    }public void addObserver(SubjectObserver observer) {
        observers.add(observer);
    }public void deleteObserver(SubjectObserver observer) {
        observers.remove(observer);
    }private void notifyObservers(){
        observers.stream().forEach(observer -> observer.update());
    }

}
ログイン後にコピー

の値が変更されると、上記の非常に単純なオブザーバーへの呼び出しがトリガーされます。実際には、保存が必要なインスタンスの変更や新旧の値の変更など、より豊富な機能を備えた API が提供されることが多いですが、これらはアクション (動作) モードを監視する必要がないため、ここでは可能な限りシンプルな例を記載しています。 。

以下にオブザーバー クラスを示します。

public static void main(String[] args) {
    User user = new User("John");
    user.addObserver(() -> System.out.println("Observable subject " + user + " has changed its state."));
    user.setName("Jack");
}
ログイン後にコピー
🎜 User クラスでは、setter メソッドを通じてステータスが変更されると、それにバインドされているオブザーバーへの呼び出しがトリガーされます。 🎜🎜 トピック オブザーバーとトピックを使用して、次の例で観察メソッドを示します: 🎜🎜
user.addObserver(() -> System.out.println("Observable subject " + user + " has changed its state."));
ログイン後にコピー
🎜🎜 User オブジェクトの状態が setter メソッドを通じて変更されるたびに、オブザーバーに通知され、メッセージがコンソールに出力されます。 。ここまでは、Observer パターンの簡単な使用例を示しました。ただし、この一見単純な使用例を通じて、この状況で制御の反転がどのように達成されるかを理解できます。 🎜🎜オブザーバーモードでは、テーマは「フレームワークレイヤー」の役割を果たし、いつ、どこで誰の呼び出しをトリガーするかを完全に制御します。オブザーバーは (トピックに登録されている限り) いつ呼び出されるかを制御できないため、オブザーバーのイニシアチブは委任されます。これは、制御の反転がどこで起こったのか、つまり観察者が主体に拘束されているとき、実際に発見できることを意味します: 🎜🎜
public abstract class EntityProcessor {public final void processEntity() {
        getEntityData();
        createEntity();
        validateEntity();
        persistEntity();
    }protected abstract void getEntityData();protected abstract void createEntity();protected abstract void validateEntity();protected abstract void persistEntity();

}
ログイン後にコピー
ログイン後にコピー
🎜

上述用例,简要说明了为什么观察者模式是实现IoC的一种非常简单的方式。正是以这种分散式设计软件组件的形式,使得控制得以发生反转。

 

模板方法模式实现IOC

模板方法模式实现的思想是在一个基类中通过几个抽象方法来定义一个通用的算法,然后让子类提供具体的实现,这样保证算法结构不变。

我们可以应用这个思想,定义一个通用的算法来处理领域实体,看例子:

public abstract class EntityProcessor {public final void processEntity() {
        getEntityData();
        createEntity();
        validateEntity();
        persistEntity();
    }protected abstract void getEntityData();protected abstract void createEntity();protected abstract void validateEntity();protected abstract void persistEntity();

}
ログイン後にコピー
ログイン後にコピー

processEntity() 方法是个模板方法,它定义了处理实体的算法,而抽象方法代表了算法的步骤,它们必须在子类中实现。通过多次继承 EntityProcessor 并实现不同的抽象方法,可以实现若干算法版本。

虽然这说清楚了模板方法模式背后的动机,但人们可能想知道为什么这是 IOC 的模式。

典型的继承中,子类调用基类中定义的方法。而这种模式下,相对真实的情况是:子类实现的方法(算法步骤)被基类的模板方法调用。因此,控制实际是在基类中进行的,而不是在子类中。

总结:

依赖注入:从客户端获得依赖关系的控制不再存在于这些类中。它存由底层的注入器 / DI 框架来处理。

观察者模式:当主体发生变化时,控制从观察者传递到主体。

模板方法模式:控制发生在定义模板方法的基类中,而不是实现算法步骤的子类中。

以上がIOC制御反転例の詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

Java フレームワークにおけるデザイン パターンとアーキテクチャ パターンの違い Java フレームワークにおけるデザイン パターンとアーキテクチャ パターンの違い Jun 02, 2024 pm 12:59 PM

Java フレームワークにおけるデザイン パターンとアーキテクチャ パターンの違いは、デザイン パターンがソフトウェア設計における一般的な問題に対する抽象的な解決策を定義し、ファクトリ パターンなどのクラスとオブジェクト間の相互作用に焦点を当てていることです。アーキテクチャ パターンは、階層化アーキテクチャなどのシステム コンポーネントの編成と相互作用に焦点を当てて、システム構造とモジュールの間の関係を定義します。

Java デザイン パターンにおけるデコレータ パターンの分析 Java デザイン パターンにおけるデコレータ パターンの分析 May 09, 2024 pm 03:12 PM

デコレータ パターンは、元のクラスを変更せずにオブジェクトの機能を動的に追加できる構造設計パターンです。抽象コンポーネント、具象コンポーネント、抽象デコレータ、具象デコレータの連携によって実装され、ニーズの変化に合わせてクラス機能を柔軟に拡張できます。この例では、ミルクとモカのデコレーターが総額 2.29 ドルで Espresso に追加されており、オブジェクトの動作を動的に変更するデコレーター パターンの力を示しています。

PHP設計パターンの実践事例分析 PHP設計パターンの実践事例分析 May 08, 2024 am 08:09 AM

1. ファクトリ パターン: オブジェクト作成とビジネス ロジックを分離し、ファクトリ クラスを通じて指定された型のオブジェクトを作成します。 2. オブザーバー パターン: サブジェクト オブジェクトが状態の変化をオブザーバー オブジェクトに通知できるようにし、疎結合とオブザーバー パターンを実現します。

Java 設計パターンにおけるアダプター パターンの素晴らしい使用法 Java 設計パターンにおけるアダプター パターンの素晴らしい使用法 May 09, 2024 pm 12:54 PM

アダプター パターンは、互換性のないオブジェクトが連携できるようにする構造設計パターンであり、オブジェクトがスムーズに対話できるように、あるインターフェイスを別のインターフェイスに変換します。オブジェクト アダプタは、適応されたオブジェクトを含むアダプタ オブジェクトを作成し、ターゲット インターフェイスを実装することにより、アダプタ パターンを実装します。実際のケースでは、クライアント (MediaPlayer など) はアダプター モードを通じて高度な形式のメディア (VLC など) を再生できますが、クライアント自体は通常のメディア形式 (MP3 など) のみをサポートします。

デザインパターンがコードメンテナンスの課題にどのように対処するか デザインパターンがコードメンテナンスの課題にどのように対処するか May 09, 2024 pm 12:45 PM

デザイン パターンは、再利用可能で拡張可能なソリューションを提供することで、コード メンテナンスの課題を解決します。 オブザーバー パターン: オブジェクトがイベントをサブスクライブし、イベントが発生したときに通知を受信できるようにします。ファクトリ パターン: 具象クラスに依存せずにオブジェクトを作成するための集中的な方法を提供します。シングルトン パターン: クラスには、グローバルにアクセス可能なオブジェクトの作成に使用されるインスタンスが 1 つだけ存在することが保証されます。

PHP デザイン パターン: テスト駆動開発の実践 PHP デザイン パターン: テスト駆動開発の実践 Jun 03, 2024 pm 02:14 PM

TDD は、高品質の PHP コードを作成するために使用されます。その手順には、テスト ケースを作成し、期待される機能を記述し、テスト ケースを失敗させることが含まれます。過度な最適化や詳細な設計を行わずに、テスト ケースのみが通過するようにコードを記述します。テスト ケースが合格したら、コードを最適化およびリファクタリングして、可読性、保守性、およびスケーラビリティを向上させます。

Java フレームワークでデザイン パターンを使用する利点と欠点は何ですか? Java フレームワークでデザイン パターンを使用する利点と欠点は何ですか? Jun 01, 2024 pm 02:13 PM

Java フレームワークでデザイン パターンを使用する利点には、コードの可読性、保守性、拡張性の向上が含まれます。欠点としては、複雑さ、パフォーマンスのオーバーヘッド、使いすぎによる学習曲線の急上昇などが挙げられます。実際のケース: プロキシ モードはオブジェクトの遅延読み込みに使用されます。デザイン パターンを賢く使用して、その利点を活用し、欠点を最小限に抑えます。

Guice フレームワークでのデザイン パターンの適用 Guice フレームワークでのデザイン パターンの適用 Jun 02, 2024 pm 10:49 PM

Guice フレームワークは、次のような多くの設計パターンを適用します。 シングルトン パターン: @Singleton アノテーションによってクラスのインスタンスが 1 つだけであることを保証します。ファクトリ メソッド パターン: @Provides アノテーションを使用してファクトリ メソッドを作成し、依存関係の注入中にオブジェクト インスタンスを取得します。戦略モード: アルゴリズムをさまざまな戦略クラスにカプセル化し、@Named アノテーションを通じて特定の戦略を指定します。

See all articles