【Java】デザインパターンをやってみた 〜 Adapter編 ~

★★★ お知らせ ★★★

◆ Cassandra Dayに登壇 6/1(木) ◆
6月1日開催のイベント Cassandra Day - Tokyo に当社のエンジニアが登壇します!
今回「Cassandra適用のポイントと実案件での苦労話」と題して、RDBMSでは実現困難であった顧客要件をCassandraで簡単に実現できる実例を踏まえて、その適用のポイントをわかりやすく解説します。
⇒ イベント詳細はこちらから

◆ 6月のPS Liveは決済サービスStripeのデモ!◆
決済サービスのStripeでサブスクリプションの支払い機能を作ってみた
Stripeの機能の一部を切り出して、簡単なサブスクリプションを作るとどうなるのかを、デモをまじえてご紹介します。
⇒ 詳細はこちらから

◆【セミナー開催】 可視化ツールGrafana~初めてのダッシュボード作成◆
デモンストレーション付き!
本セミナーでは、売上データを用いて、4種類のパネル作成方法をお見せします。
⇒ お申込みはこちらから

◆ エンジニア業務環境アンケート結果 ◆
エンジニアが自分の働き方にどういったことで満足していて、不満を感じているのか、働きたい会社像として何を求めているのか、業務環境調査を実施しました。ぜひご覧ください。
⇒ アンケート結果はこちらから

こんにちは。サイオステクノロジーの川田です。

今回はAdapterパターンについて調べてみました。
参考☞「増補改訂版Java言語で学ぶデザインパターン入門

Adapterとは

「Adapt」とは適応させるという意味です。
適応させると言葉で言われてもパッとしません。

よく例に出てくるのがACアダプタです。簡単に言うとズバリ仲介人です。

ACアダプタはコンセントからくる電気をパソコンで使える電気に変換する役割をしてくれます。

クラス図で考える

先ほどはACアダプタを使って例えてみました。
ではプログラミングではどのように考えるのかクラス図で見てみます。

役割分担
Client :Targetメソッドを使って処理を行う
Target :必要とされるメソッド
Adapter:Adapteeのメソッドを使ってTargetの役割を満たすためのクラス
Adaptee:すでに用意されているメソッドを持っているクラス

AdapterとなるPrintHumanクラスはHumanクラスを継承(extends)し、Printインターフェースを実装(implements)しています。

実装してみる

Adapteeの部分です。

  • Human.java
public class Human {
    private String name;
    private int birthday;

    public Human(String name, int birthday){
        this.name = name;
        this.birthday = birthday;
    }
    public void showName(){
        System.out.println(name);
    }
    public void showBirthday(){
        System.out.println(birthday);
    }
}

Targetで必要とされているメソッドを定めています。

  • Print.java
public interface Print {
    public abstract void printName();
    public abstract void printAge();
}

本日の主役、Adapterの役割です。
HumanクラスをextendsしてshowNameとshowBirthdayメソッドを継承しています。
Printインターフェースをimplementsし、printNameとprintBirthdayを実装しています。

  • PrintHuman.java
public class PrintHuman extends Human implements Print{
    public PrintHuman(String name, int birthday){
        super(name, birthday);
    }
    public void printName(){
        showName();
    }
    public void printBirthday(){
        showBirthday();
    }
}

これらのクラスやインターフェースを利用するmainメソッドは以下の通りです。

  • Main.java
public class Main {
    public static void main(String[] agrs){
        Print p = new PrintHuman("taro", 19990101);
        p.printName();
        p.printBirthday();
    }
}

実行結果はこちらです。

taro
19990101

MainクラスはPrintインターフェースのprintNameとprintBirthdayメソッドを使っています。
Adapterがどんな実装になっているかなんてMainクラスは知らないのです!
既に提供されているもの、それがHumanクラスだとします。
PrintHumanクラスはHumanクラスの実装を利用できるように変換する役割を担ってくれました。

委譲

先ほどのは継承を使ったAdapterパターンでした。
実はもう一つ、委譲を使ったAdapterパターンもあります。

委譲とは他にゆだね、ゆずるという意味になります。
今回の委譲の表現は「あるメソッドの処理を他のクラスのインスタンスにお任せする」という考えになります。

クラス図(委譲)

右上は先ほど出てきた「継承を使った」クラス図です。
比べてみると赤丸の部分が変わっていることがわかりますね。

実装で確認してみましょう!

実装してみる

Print.javaとPrintHuman.javaを修正します。

  • Print.java
public abstract class Print {
    public abstract void printName();
    public abstract void printBirthday();
}

Printはインターフェースではなく、クラスに修正します。

  • PrintHuman.java
public class PrintHuman extends Print{
    private Human human;
    public PrintHuman(String name, int age){
        human = new Human(name, age);
    }
    public void printName(){
        human.showName();
    }
    public void printAge(){
        human.showBirthday();
    }
}

1行目ではPrintをextendsしています。
そして2行目でHumanクラスのインスタンスを保持しています。
showNameとshowBirthdayの呼び出し方がhumanフィールドを経由して呼び出していることがわかりますね!

printNameやprintBirthdayメソッドが呼ばれたらHumanクラスのインスタンスにお任せしているということです。
実行結果は変わりません。

taro
19990101

まとめ

今回はAdapterパターンの継承と委譲について学びました。
既存のソースをいじらずに修正ができればテストの手間も省けますね!

アバター画像
About kawada 25 Articles
Webアプリケーション開発を行っており、プログラミング初心者向けの記事や動画編集に関する内容を中心とした記事を執筆しています。
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる