IOC
1質問リード
ソフトウェア開発の過程では、依存は避けられません。次の図に示すように、ブリッジモードを例として取り上げます。
FaceモジュールはExecutorモードを使用する必要があります。設計の観点から、Faceは抽象Executor、つまりAbstractExecutorを直接使用することが望まれます。ただし、実際のプロセスでは、最初にAbstractExecutorのインスタンスを作成する必要がある場合は、新しいExecutorImplに移動する必要があります。このクラスがコードで広く使用されていると仮定すると、新しいExecutorImplのようなコードが多くの場所に表示されます。新しいクラスExecutorImplTwoを拡張したら、これらの新しいExecutorImplのコードを変更する必要があります。これは、開閉の原則に重大な違反をします。
この問題を解決するために、ファクトリーモデルが登場しました。ファクトリパターンを使用して、新しいExecutorImplのプロセスをラップします。新しいExecutorImplを新しいExecutorImplTwoに変更する必要がある場合は、ファクトリクラスの実装のみを変更する必要があります。これである程度問題は解決しました。しかし、それはまだ軟膏にハエがあります:
- ExecutorImplの変更時に変更する必要のあるコードの行数はある程度削減されていますが、それでも完全に変更されているわけではありません。つまり、厳密な開閉はありません。
- Executor実装クラスの構築パラメータに一貫性がない場合、現時点ではファクトリメソッドが有効でない可能性があります。現時点では、抽象ファクトリを使用すると言う人もいますが、残念ながら、問題を抽象ファクトリに投げると、抽象ファクトリの構築プロセスとインターフェイスパラメータの構築も同じ問題に直面します。つまり、問題を抽象ファクトリに渡しただけで、根本的に問題は解決しませんでした。
2問題を解決する
上記の問題を解決するには、オブジェクト指向の設計原理である制御の反転(IOC)を実現する必要があります。最も一般的な実装は、依存性注入(つまり、DI)です。最も有名なものの1つは、Java言語のリフレクション機能に基づく強力な依存性注入フレームワークであるSpringの依存性注入機能です。もちろん、依存性注入はその強力な機能の1つにすぎません。C ++言語の場合、リフレクションはありません。同様のリフレクション関数は、テンプレートを使用して実現できます。
AOP
1質問リード
開発では、ログの印刷、インターセプト、フィルタリングの追加など、関数呼び出しの前後にいくつかの補足関数を追加する必要があることがよくあります。現時点では、テンプレートモードまたはデコレータモードを使用して同様の機能を実現できます。
テンプレートメソッドは次のとおりです。
装飾モードは次のとおりです。
テンプレートメソッドであろうと装飾モードであろうと、実装者は固定ルーチンに従ってコードを記述する必要があります。呼び出すコードが記述された3番目のコードであり、期待どおりに実装されない場合、テンプレートメソッドと装飾モードは機能しません。アピアランスモードを使用してパッケージ化できると言う人もいますが、ログを1行追加するだけでよい場合、大量のコードパッケージを動員するコストは現実的ではありません。さらに、シームレスに追加すると、すでに他の人が書いたコードの呼び出しフロー現時点では、従来のモデルでは、既存のコードを変更せずに関数をシームレスに挿入することはできません。
2問題を解決する
前の問題を解決するために、プログラミングのアイデアAOP(アスペクト指向プログラム)、すなわちアスペクト指向プログラミングが提案されました。Javaの強力な動的プロキシメカニズムの下で、AOPの技術的な実現可能性を提供します。もちろん、C ++はテンプレートを使用して大まかなAOPを実現することもできますが、それでも呼び出し元には認識されます。スプリングライブラリのAOPは次のように使用されます。
- インターフェースを定義する
public interface HelloWorld
{
void print();
}
- インターフェイスを実装する
public class HelloWorldImpl implements HelloWorld
{
public void print()
{
System.out.println("Enter HelloWorldImpl.print()");
}
}
- 側面を実現する
public class TestHandler
{
public void test()
{
System.out.println("TestHandler Interceptor");
}
}
- Spring構成ファイルaoptest.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd">
<bean id="HelloWorldImpl" class="com.example.aop.HelloWorldImpl" />
<bean id="TestHandler" class="com.example.aop.TestHandler" />
<aop:config>
<aop:aspect id="cutin" ref="TestHandler">
<aop:pointcut id="allMethod" expression="execution(*com.example.aop.HelloWorld.*(..))" />
<aop:before method="test" pointcut-ref="allMethod" />
<aop:after method="test" pointcut-ref="allMethod" />
</aop:aspect>
</aop:config>
</beans>
- AOPを使用する
public static void main(String[] args)
{
ApplicationContext ctx =
new ClassPathXmlApplicationContext("aoptest.xml");
HelloWorld hw = (HelloWorld)ctx.getBean("HelloWorldImpl");
hw.print();
}
- テスト出力は次のとおりです。
TestHandler Interceptor
Enter HelloWorldImpl.print()
TestHandler Interceptor
総括する
それがIOCであろうとAOPであろうと、その出現は新しいアイデアや新しいアイデアのためではありません。優れたテクノロジーは、実際のビジネス目標を最優先事項として解決することです。彼らの直接の目標は、分離して、開閉の原則に厳密に準拠させることです。基本的な目標は、開発とコラボレーションを促進すること、つまり、依存関係と並行開発を分離することです。