![Adapter](/images/patterns/cards/adapter-mini.png?id=b2ee4f681fb589be5a0685b94692aebb)
Adapter を Java で
Adapter は、 構造に関するデザインパターンの一つで、 非互換なオブジェクト同士の協働を可能とします。
アダプターは二つのオブジェクト間のラッパーとして機能します。 一方のオブジェクトへの呼び出しを捕まえ、 二つ目のオブジェクトが認識可能なデータ形式とインターフェースに変換します。
複雑度:
人気度:
使用例: Adapter パターンは Java コードではよく見かけます。 旧来のコードに基づいたシステムでよく使用されます。 そのような場合、 アダプターは旧来のコードを現代のクラスから使用可能にします。
Java コア・ライブラリーには、 いくつかの標準アダプターがあります:
-
java.util.Arrays#asList()
-
java.util.Collections#list()
-
java.util.Collections#enumeration()
-
java.io.InputStreamReader(InputStream)
(Reader
オブジェクトを返す) -
java.io.OutputStreamWriter(OutputStream)
(Writer
オブジェクトを返す) -
javax.xml.bind.annotation.adapters.XmlAdapter#marshal()
および#unmarshal()
見つけ方: アダプターは、 異なる抽象クラスまたはインターフェース型のインスタンスを取るコンストラクターの存在により認識できます。 アダプターは、 いずれかのメソッドへの呼び出しを受け取ると、 パラメーターを適切な形式に変換し、 ラップされたオブジェクトの一つまたは複数のメソッドを呼び出します。
四角いくいを丸い穴に合わせる
この簡単な例では、 アダプターが互換性のないオブジェクト同士を動作させる方法を示します。
round
round/RoundHole.java: 丸い穴
package refactoring_guru.adapter.example.round;
/**
* RoundHoles are compatible with RoundPegs.
*/
public class RoundHole {
private double radius;
public RoundHole(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public boolean fits(RoundPeg peg) {
boolean result;
result = (this.getRadius() >= peg.getRadius());
return result;
}
}
round/RoundPeg.java: 丸いくい
package refactoring_guru.adapter.example.round;
/**
* RoundPegs are compatible with RoundHoles.
*/
public class RoundPeg {
private double radius;
public RoundPeg() {}
public RoundPeg(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
}
square
square/SquarePeg.java: 正方形のくい
package refactoring_guru.adapter.example.square;
/**
* SquarePegs are not compatible with RoundHoles (they were implemented by
* previous development team). But we have to integrate them into our program.
*/
public class SquarePeg {
private double width;
public SquarePeg(double width) {
this.width = width;
}
public double getWidth() {
return width;
}
public double getSquare() {
double result;
result = Math.pow(this.width, 2);
return result;
}
}
adapters
adapters/SquarePegAdapter.java: 正方形のくいの丸い穴へのアダプター
package refactoring_guru.adapter.example.adapters;
import refactoring_guru.adapter.example.round.RoundPeg;
import refactoring_guru.adapter.example.square.SquarePeg;
/**
* Adapter allows fitting square pegs into round holes.
*/
public class SquarePegAdapter extends RoundPeg {
private SquarePeg peg;
public SquarePegAdapter(SquarePeg peg) {
this.peg = peg;
}
@Override
public double getRadius() {
double result;
// Calculate a minimum circle radius, which can fit this peg.
result = (Math.sqrt(Math.pow((peg.getWidth() / 2), 2) * 2));
return result;
}
}
Demo.java: クライアント・コード
package refactoring_guru.adapter.example;
import refactoring_guru.adapter.example.adapters.SquarePegAdapter;
import refactoring_guru.adapter.example.round.RoundHole;
import refactoring_guru.adapter.example.round.RoundPeg;
import refactoring_guru.adapter.example.square.SquarePeg;
/**
* Somewhere in client code...
*/
public class Demo {
public static void main(String[] args) {
// Round fits round, no surprise.
RoundHole hole = new RoundHole(5);
RoundPeg rpeg = new RoundPeg(5);
if (hole.fits(rpeg)) {
System.out.println("Round peg r5 fits round hole r5.");
}
SquarePeg smallSqPeg = new SquarePeg(2);
SquarePeg largeSqPeg = new SquarePeg(20);
// hole.fits(smallSqPeg); // Won't compile.
// Adapter solves the problem.
SquarePegAdapter smallSqPegAdapter = new SquarePegAdapter(smallSqPeg);
SquarePegAdapter largeSqPegAdapter = new SquarePegAdapter(largeSqPeg);
if (hole.fits(smallSqPegAdapter)) {
System.out.println("Square peg w2 fits round hole r5.");
}
if (!hole.fits(largeSqPegAdapter)) {
System.out.println("Square peg w20 does not fit into round hole r5.");
}
}
}
OutputDemo.txt: 実行結果
Round peg r5 fits round hole r5.
Square peg w2 fits round hole r5.
Square peg w20 does not fit into round hole r5.