ビジターモードとASMの詳細説明
この記事へのリンク: https://blog.csdn.net/feather_wch/article/details/131756394
記事ディレクトリ
1. 訪問者パターンは行動パターンです
2. 定義: クラスの内部構造が変更されていない場合、このオブジェクトにアクセスするときに、訪問者ごとに異なる処理メソッドが表示されます。
クラス構造は変わらないが操作処理ロジックは変更可能であるという問題を解決するために、データに対するすべての操作をビジタークラスにカプセル化し、構造クラスを変更せずに別のビジターを呼び出すだけで済みます。
[デザインパターン] ビジターパターンは、確かに最も複雑なデザインパターンの 1 つです。
3. 開閉原則の違反
- 要素を追加するには、Visitor と各 ConcreateVisitor を変更する必要があります
構造
訪問者パターンの基本構造には次の役割が含まれます。
- 抽象要素 (要素): 訪問者 (通常は ) を受け入れるメソッドを定義します
accept(Visitor visitor)
。==> ドリンクなど - ConcreteElement: 抽象要素 (通常は ) の accept メソッドを実装します
visitor.visit(this)
。==> ミルクティー、フルーツティーなど - 抽象訪問者 (Visitor): 各具象要素 (通常は ) のアクセス操作を定義します
visit(ConcreteElement element)
。==> メンバー - 特定の訪問者 (ConcreteVisitor): 抽象訪問者の訪問操作を実装し、特定の要素のタイプに応じて対応するロジックを実行します。⇒ シルバー会員、プラチナ会員、ダイヤモンド会員
- オブジェクト構造 (ObjectStructure): 要素のコレクションを維持し、要素を横断するメソッドを提供し、訪問者が各要素にアクセスできるようにします。==> ミルクティーショップ
ミルクティーショップではミルクティーとフルーツティーの種類が異なり、同じ商品でも会員ごとに割引率が異なります。
抽象的な要素: ドリンク
public interface Beverage {
void accept(Visitor visitor); // 访问
int getPrice(); // 获得价格
}
特定の要素: シェンシェンウーロン、オーキッドラテ
飲料インターフェイスを実装するために、accept は引き続き訪問者に渡されて処理されます。
public class ShengShengWuLong implements Beverage {
int price;
public ShengShengWuLong(int price) {
this.price = price;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public int getPrice() {
return price;
}
}
public class YoulanLatte implements Beverage {
int price;
public YoulanLatte(int price) {
this.price = price;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
@Override
public int getPrice() {
return price;
}
}
抽象的な訪問者: 訪問者
特定の要素の数に応じて、訪問方法を定義します
public abstract class Visitor {
abstract void visit(ShengShengWuLong wulong);
abstract void visit(YoulanLatte latte);
}
特定の訪問者
シルバー メンバー、ゴールド メンバー、ダイヤモンド メンバーは、
訪問メソッドを実装し、処理ロジックをカスタマイズします。
public class SilverClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("白银客户 喝到:"+wulong.getClass().getSimpleName() + " 9折:" + (0.9 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("白银客户 喝到:"+latte.getClass().getSimpleName() + " 9折:" + (0.9 * latte.getPrice()));
}
}
public class GoldClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("黄金客户 喝到:"+wulong.getClass().getSimpleName() + " 8折:" + (0.8 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("黄金客户 喝到:"+latte.getClass().getSimpleName() + " 8折:" + (0.8 * latte.getPrice()));
}
}
public class DiamondClient extends Visitor {
@Override
void visit(ShengShengWuLong wulong) {
System.out.println("钻石客户 喝到:"+wulong.getClass().getSimpleName() + " 7折:" + (0.7 * wulong.getPrice()));
}
@Override
void visit(YoulanLatte latte) {
System.out.println("钻石客户 喝到:"+latte.getClass().getSimpleName() + " 7折:" + (0.7 * latte.getPrice()));
}
}
オブジェクト構造: Cha Yan Yue Se Store
- さまざまな飲み物を保管
- 訪問者に提供するサービスインターフェース
public class Store {
List<Beverage> drinks = new ArrayList<>();
public void addBeverage(Beverage beverage){
drinks.add(beverage);
}
public void accept(Visitor visitor){
for (Beverage beverage : drinks) {
beverage.accept(visitor);
}
}
}
テストクラス
public class Main {
public static void main(String[] args) {
Store store = new Store();
store.addBeverage(new ShengShengWuLong(32));
store.addBeverage(new YoulanLatte(26));
store.accept(new SilverClient());
store.accept(new GoldClient());
store.accept(new DiamondClient());
}
}
ASMの訪問者パターン
1. ASMとは何ですか? =>ASMフレームワークはバイトコード(クラスファイル)を書き換えたり直接書き込んだりして新しいクラスを生成します
JDK 動的プロキシ (Proxy.newProxyInstance) と比較すると、後者はリフレクションを使用するのに対し、前者は必要なクラスの動作を直接生成するため、パフォーマンスが高くなります。
2. ASM はなぜ訪問者パターンを使用するのですか?
- JVM仕様のクラスファイルは固定構造になっています
3. ASM はどのように実装されますか?
- 固定メソッドエリアを見つけてメソッドエリアコードを変更します。
- 変更方法、訪問者を定義して動作ロジックを決定する
4. ASMコンポーネントと訪問者比較表
1. 抽象要素 (Element)
2. 具体要素 (ConcreteElement)
- 抽象要素と具象要素は、クラス、フィールド、メソッド、命令、注釈など、バイトコード内のさまざまなコンポーネントを指します。
3. 抽象訪問者 (Visitor) => ClassVisitor、MethodVisitor、FieldVisitor、SignatureVisitor
4. 特定の訪問者 (ConcreteVisitor) => ClassWriter、AdviceAdapter(MethodVisitor)
- クラス、フィールド、メソッドなどの要素へのアクセスが実現されます。
5. オブジェクト構造(ObjectStructure) => ClassReader
- クラス ファイルを読み取り、それらを一連のイベントに変換し、処理のために ClassVisitor に渡します。
- ClassVisitor をパラメータとして受け入れる accept メソッドを提供します
MethodVisitor は抽象ビジターでもあり、メソッド内の命令、変数、ラベル、例外などの要素へのアクセス操作を定義し、通常は Visit (ConcreteElement 要素) です。MethodVisitor は、AdviceAdapter、GeneratorAdapter などの複数の特定のサブクラスを持つこともでき、それらはすべてメソッド内の要素へのアクセスを実装します。AdviceAdapter はメソッドの最初と最後にコードを挿入する役割を果たし、GeneratorAdapter は一般的に使用される命令を生成する役割を果たします。
ClassReaderの読み込み処理
ClassReader
->读取到一个类
->ClassVisitor.visit 传递一些类的信息
->读取到一个字段
->ClassVisitor.visitField 传递一些字段的信息
->读取到一个方法
->ClassVisitor.visitMethod方法 传递一些方法的信息
->返回MethodVisitor对象:定义了对方法中的指令、变量、标签、异常等元素的访问操作
->继续读取这个方法中的元素
->MethodVisitor.visit方法 传递一些元素的信息