Adapterパターン
二つのオブジェクトの間に入って、インターフェースを合わせる
adaptという単語は日本語で「適合させる」という意味で、adapterとは「適合させるもの」という意味になります。Adapterパターンは、インタフェースに互換性の無いクラス同士を組み合わせることを目的としたパターンです。
適用方法として以下の3つがあります。
インターフェース変換
例えば、これまで利用していたメソッドと同じ機能を、よりすぐれた形で提供するメソッドを持つクラスの存在を知ったとします。しかし、このすぐれたメソッドは、これまで利用していたメソッドとは異なるインタフェースを持つため、乗り換えるとなると多大な変更を余儀なくされる場合があります。こんなとき、この2つのメソッドのインタフェースの違いを吸収してやる Adapter を準備することで、少ない変更で新しいメソッドに乗り換えることができるのです。
インターフェース補完
親クラスもしくはインターフェースを継承する場合、その全抽象メソッドを実装しなければなりません。そのとき、親子関係の間に入って全抽象メソッドのデフォルトの機能を持ったメソッドを実装し、そのクラスでは必要なメソッドだけ実装すればいいようにします。
protectedメソッドを使用可能にする
対象オブジェクトのメソッドが protected だったとしても、対象オブジェクトを継承したサブクラスで publicメソッドとして提供します。
すでに作られたクラスがあって、新しいインターフェースに適合させると考えると、つい既存のクラスのソースをいじって「修正」しようと考えてしまいます。でもそれでは、動作確認がされている既存のクラスを修正後にもう一度テストしなければならなくなってしまいます。
Adapterパターンは、既存のクラスにはまったく手を加えずに、目的のインターフェースにあわせようとするものです。また、 Adapterパターンでは、既存のクラスのソースが必ずしも必要ではありません。既存のクラスの仕様だけわかれば、新しいクラスを作ることができるのです。
また、古い版と新しい版とを共存させているときに、新しい版のみ改修したくなった場合も、新しい版のクラスを使って古い版のメソッドを実装するAdapter役のクラスを作ればよいのです。
例題
getAngleBracketString()
getDoubleAngleBracketString()
与えられた文字列 AAAAA を「AAAAA」として表示する printArticleName、『AAAAA』として表示する printBookName を持つクラスを、IPrint インタフェース(C++ の場合は、純粋仮想関数のみを持つ Print 抽象クラス)にあわせて作りなさい。
ただし、IPrint インタフェース(C++ では Print 抽象クラス)にはあっていないが、すでに同様の処理をする Bracket クラスがあります。
『Hello』
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.java public class PrintQuotedBook implements IPrint {
private String message;
public PrintQuotedBook(String message) {
this.message = message;
}
public void printArticleName() {
System.out.println("「" + message + "」");
}
public void printBookName() {
System.out.println("『" + message + "』");
}
}
Main.java public class Main {
public static void main(String[] args) {
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
}
}
|
Adapterパターンを使用した例 PrintQuotedBook.java public class PrintQuotedBook extends Bracket implements IPrint {
public PrintQuotedBook(String message) {
super(message);
}
public void printArticleName() {
System.out.println(getAngleBracketString());
}
public void printBookName() {
System.out.println(getDoubleAngleBracketString());
}
}
Main.java public class Main {
public static void main(String[] args) {
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
}
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.java public class PrintQuotedBook implements IPrint {
private Bracket bracket;
public PrintQuotedBook(String message) {
bracket = new Bracket(message);
}
public void printArticleName() {
System.out.println(bracket.getAngleBracketString());
}
public void printBookName() {
System.out.println(bracket.getDoubleAngleBracketString());
}
}
Java では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、抽象クラス
|
Adapterパターンを使用しない例 printQuotedBook.h #include <string>
#include "print.h"
class PrintQuotedBook : private Bracket, public Print
{
public:
PrintQuotedBook(void);
PrintQuotedBook(std::string);
virtual ~PrintQuotedBook(void);
void printArticleName(void);
void printBookName(void);
}; printQuotedBook.cpp #include <iostream>
using namespace std;
#include "printQuotedBook.h"
PrintQuotedBook::PrintQuotedBook(void) {}
PrintQuotedBook::PrintQuotedBook(string message) : message(message) {}
PrintQuotedBook::~PrintQuotedBook(void) {}
void PrintQuotedBook::printArticleName(void)
{
cout << "「" + message + "」" << endl;
}
void PrintQuotedBook::printBookName(void)
{
cout << "『" + message + "』" << endl;
}
main.cpp #include "printBanner.h"
int main() {
PrintQuotedBook p("Hello");
p.printArticleName();
p.printBookName();
return 0;
} |
Adapterパターンを使用した例 printQuotedBook.h #include "bracket.h"
#include "print.h"
class PrintQuotedBook : private Bracket, public Print
{
public:
PrintQuotedBook(void);
PrintQuotedBook(std::string);
virtual ~PrintQuotedBook(void);
void printArticleName(void);
void printBookName(void);
}; printQuotedBook.cpp #include <iostream>
using namespace std;
#include "printQuotedBook.h"
PrintQuotedBook::PrintQuotedBook(void) {}
PrintQuotedBook::PrintQuotedBook(string message) : Bracket(message) {}
PrintQuotedBook::~PrintQuotedBook(void) {}
void PrintQuotedBook::printArticleName(void) {
cout << getAngleBracketString() << endl;
}
void PrintQuotedBook::printBookName(void) {
cout << getDoubleAngleBracketString() << endl;
}
main.cpp #include "printQuotedBook.h"
int main() {
PrintQuotedBook p("Hello");
p.printQuotedBook();
p.printBookName();
return 0;
} |
|
同様の表示をする Bracket クラスがありますが、この PrintQuotedBook クラスでは使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
この PrintQuotedBook クラスでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 また、Bracket クラスの継承には、private と記述していますが、これは Bracket クラスのメソッドを他のクラスから利用できなくするためです。クラスに不必要なメソッドを使えなくします。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、BSracket クラス内のメソッドを呼び出すわけです。 printQuotedBook.h #include "bracket.h"
#include "print.h"
using namespace std;
class PrintQuotedBook : public Print
{
private:
Bracket* bracket;
public:
PrintQuotedBook(void);
PrintQuotedBook(std::string);
virtual ~PrintQuotedBook(void);
void printArticleName(void);
void printBookName(void);
}; printQuotedBook.cpp #include <iostream>
#include "printQuotedBook.h"
PrintQuotedBook::PrintQuotedBook(void) {
}
PrintQuotedBook::PrintQuotedBook(string message) {
bracket = new Bracket(message);
}
PrintQuotedBook::~PrintQuotedBook(void) {}
void PrintQuotedBook::printArticleName(void) {
cout << bracket->getAngleBracketString() << endl;
}
void PrintQuotedBook::printBookName(void) {
cout << bracket->getDoubleAngleBracketString() << endl;
}
|
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.cs public class PrintQuotedBook : IPrint
{
private string message;
public PrintQuotedBook(string message)
{
this.message = message;
}
public void PrintArticleName()
{
Console.WriteLine("「" + message + "」");
}
public void PrintBookName()
{
Console.WriteLine("『" + message + "』");
}
}
Program.cs class Program
{
static void Main(string[] args)
{
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.PrintArticleName();
p.PrintBookName();
}
}
|
Adapterパターンを使用した例 PrintQuotedBook.cs public class PrintQuotedBook : bracket, IPrint
{
public PrintQuotedBook(string message) : base(message) { }
public void printArticleName()
{
Console.WriteLine(base.GetAngleBracketString());
}
public void PrintQuotedBook()
{
Console.WriteLine(base.GetDoubleAngleBracketString());
}
[System.Obsolete("使用できません。", true)]
public new string GetAngleBracketString()
{
return null;
}
[System.Obsolete("使用できません。", true)]
public new string GetDoubleAngleBracketString()
{
return null;
}
}
Program.cs class Program
{
static void Main(string[] args)
{
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.PrintArticleName();
p.PrintBookName();
}
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、 Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.cs public class PrintQuotedBook : IPrint
{
private Bracket bracket;
public PrintQuotedBook(string message)
{
bracket = new Bracket(message);
}
public void printArticleName()
{
Console.WriteLine(bracket.GetAngleBracketString());
}
public void PrintQuotedBook()
{
Console.WriteLine(bracket.GetDoubleAngleBracketString());
}
}
|
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.vb Public Class PrintQuotedBook
Implements IPrint
Private message As String
Public Sub New(ByVal message As String)
MyClass.message = message
End Sub
Public Sub PrintArticleName() Implements IPrint.PrintArticleName
Console.WriteLine("「" & message & "」")
End Sub
public Sub PrintBookName() Implements IPrint.PrintBookName
Console.WriteLine("『" & message & "』")
End Sub
End Class
Program.vb Module Main
Sub Main()
Dim p As PrintQuotedBook = New PrintQuotedBook("Hello")
p.PrintArticleName()
p.PrintBookName()
End Sub
End Module
|
Adapterパターンを使用した例 PrintQuotedBook.vb Public Class PrintQuotedBook
Inherits Bracket
Implements IPrint
Public Sub New(ByVal message As String)
MyBase.New(message)
End Sub
Public Sub PrintArticleName() Implements IPrint.PrintArticleName
Console.WriteLine(MyBase.GetAngleBracketString())
End Sub
Public Sub PrintBookName() Implements IPrint.PrintBookName
Console.WriteLine(MyBase.GetDoubleAngleBracketString())
End Sub
<Obsolete("使用できません。", True)>
Public Overloads Function GetAngleBracketString() As String
Return Nothing
End Function
<Obsolete("使用できません。", True)>
Public Overloads Function GetDoubleAngleBracketString() As String
Return Nothing
End Function
End Class
Program.vb Module Main
Sub Main()
Dim p As PrintQuotedBook = New PrintQuotedBook("Hello")
p.PrintArticleName()
p.PrintBookName()
End Sub
End Module
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.vb Public Class PrintQuotedBook
Implements IPrint
Private bracket As Bracket
Public Sub New(ByVal message As String)
bracket = New Bracket(message)
End Sub
Public Sub PrintArticleName() Implements IPrint.PrintArticleName
Console.WriteLine(bracket.GetAngleBracketString())
End Sub
Public Sub PrintBookName() Implements IPrint.PrintBookName
Console.WriteLine(bracket.GetDoubleAngleBracketString())
End Sub
End Class
|
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.js module.exports = class PrintQuotedBook {
constructor(message) {
this.message = message;
}
printArticleName() {
process.stdout.write("「" + message + "」\n");
}
printBookName() {
process.stdout.write("『" + message + "』\n");
}
}
Main.java const PrintQuotedBook = require("./PrintQuotedBook.js");
let p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
|
Adapterパターンを使用した例 PrintQuotedBook.js const IPrint = require("./IPrint.js");
const Bracket = require("./Bracket.js");
module.exports = class PrintQuotedBook extends IPrint {
constructor(message) {
super();
this.bracket = new Bracket(message);
}
printArticleName() {
process.stdout.write(
this.bracket.getAngleBracketString() + "\n");
}
printBookName() {
process.stdout.write(
this.bracket.getDoubleAngleBracketString() + "\n");
}
}
Main.java const PrintQuotedBook = require("./PrintQuotedBook.js");
let p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスに移譲して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.pm package PrintQuotedBook {
use base qw(IPrint);
sub new {
my ($class, $message) = @_;
my $this = { message => $message };
return bless $this, $class;
}
sub printArticleName {
my ($this) = @_;
print "「" + $this->{message} + "」\n";
}
sub printBookName {
my ($this) = @_;
print "『" + $this->{message} + "』\n";
}
}
Main.pl use lib qw(./);
use PrintQuotedBook;
my $p = new PrintQuotedBook("Hello");
$p->printArticleName();
$p->printBookName();
|
Adapterパターンを使用した例 PrintQuotedBook.pm package PrintQuotedBook {
use base qw(Bracket IPrint);
sub new {
my ($class, $message) = @_;
my $this = $class->SUPER::new($message);
return bless $this, $class;
}
sub printArticleName {
my ($this) = @_;
print $this->getAngleBracketString() . "\n";
}
sub printBookName {
my ($this) = @_;
print $this->getDoubleAngleBracketString() . "\n";
}
}
Main.pl use lib qw(./);
use PrintQuotedBook;
my $p = new PrintQuotedBook("Hello");
$p->printArticleName();
$p->printBookName();
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.pm package PrintQuotedBook {
use base qw(IPrint);
sub new {
my ($class, $message) = @_;
my $this = { brackt => new Bracket($message) };
return bless $this, $class;
}
sub printArticleName {
my ($this) = @_;
print $this->{brackt}->getAngleBracketString() . "\n";
}
sub printBookName {
my ($this) = @_;
print $this->{brackt}->getDoubleAngleBracketString() . "\n";
}
}
Perl では、継承した基底クラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.rb require './IPrint'
class PrintQuotedBook
def initialize(message)
@message = message
end
def printArticleName()
puts "「" + message + "」"
end
def printBookName()
puts "『" + message + "』"
end
end
Main.rb require './PrintQuotedBook'
p = PrintQuotedBook.new("Hello")
p.printArticleName()
p.printBookName()
|
Adapterパターンを使用した例 PrintQuotedBook.rb require './IPrint'
require './Bracket'
class PrintQuotedBook < IPrint
def initialize(message)
super();
@bracket = Bracket.new(message);
end
def printArticleName()
puts @bracket.getAngleBracketString()
end
def printBookName()
puts @bracket.getDoubleAngleBracketString()
end
end
Main.rb require './PrintQuotedBook'
p = PrintQuotedBook.new("Hello")
p.printArticleName()
p.printBookName()
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスに移譲して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.py class PrintQuotedBook:
def __init__(self, message):
self.message = message
def printArticleName(self):
print(f"「{self.message}」")
def printBookName(self):
print(f"『{self.message}』")
Main.py from PrintQuotedBook import PrintQuotedBook
p = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
|
Adapterパターンを使用した例 PrintQuotedBook.py from IPrint import IPrint
from Bracket import Bracket
class PrintQuotedBook(Bracket, IPrint):
def __init__(self, message):
super().__init__(message)
def printArticleName(self):
print(super().getAngleBracketString())
def printBookName(self):
print(super().getDoubleAngleBracketString())
Main.py from PrintQuotedBook import PrintQuotedBook
p = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.py from IPrint import IPrint
from Bracket import Bracket
class PrintQuotedBook(IPrint) :
def __init__(self, message):
self.bracket = Bracket(message)
def printArticleName(self):
print(self.bracket.getAngleBracketString())
def printBookName(self):
print(self.bracket.getDoubleAngleBracketString())
Python では、継承した基底クラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.php <?php
require_once('IPrint.php');
class PrintQuotedBook implements IPrint {
public function __construct($message) {
$this->message = $message;
}
public function printArticleName() {
print "「" . message . "」\n";
}
public void printBookName() {
print "『" . message . "』\n";
}
}
?>
Main.java <?php
require_once('PrintQuotedBook.php');
$p = new PrintQuotedBook("Hello");
$p->printArticleName();
$p->printBookName();
?>
|
Adapterパターンを使用した例 PrintQuotedBook.java <?php
require_once('Bracket.php');
require_once('IPrint.php');
class PrintQuotedBook extends Bracket implements IPrint {
public function __construct($message) {
parent::__construct($message);
}
public function printArticleName() {
print parent::getAngleBracketString() . "\n";
}
public function printBookName() {
print parent::getDoubleAngleBracketString() . "\n";
}
}
?>
Main.java <?php
require_once('PrintQuotedBook.php');
$p = new PrintQuotedBook("Hello");
$p->printArticleName();
$p->printBookName();
?>
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.java <?php
require_once('Bracket.php');
require_once('IPrint.php');
class PrintQuotedBook implements IPrint {
public function __construct($message) {
$this->bracket = new Bracket($message);
}
public function printArticleName() {
print $this->bracket->getAngleBracketString() . "\n";
}
public function printBookName() {
print $this->bracket->getDoubleAngleBracketString() . "\n";
}
}
?>
PHP では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.ts import {IPrint} from "./IPrint";
export
class PrintQuotedBook implements IPrint {
private message:string;
public constructor(message:string) {
this.message = message;
}
public printArticleName():void {
process.stdout.write("「" + this.message + "」");
}
public printBookName():void {
process.stdout.write("『" + this.message + "』");
}
}
Main.ts import {PrintQuotedBook} from "./PrintQuotedBook";
let p:PrintQuotedBook = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
|
Adapterパターンを使用した例 PrintQuotedBook.ts import {IPrint} from "./IPrint";
import {Bracket} from "./Bracket";
export
class PrintQuotedBook extends Bracket implements IPrint {
public constructor(message:string) {
super(message);
}
public printArticleName():void {
process.stdout.write(this.getAngleBracketString() + "\n");
}
public printBookName():void {
process.stdout.write(this.getDoubleAngleBracketString() + "\n");
}
}
Main.ts import {PrintQuotedBook} from "./PrintQuotedBook";
let p:PrintQuotedBook = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.ts import {IPrint} from "./IPrint";
import {Bracket} from "./Bracket";
export
class PrintQuotedBook implements IPrint {
private bracket:Bracket;
public constructor(message:string) {
bracket = new Bracket(message);
}
public printArticleName():void {
process.stdout.write(this.bracket.getAngleBracketString());
}
public printBookName():void {
process.stdout.write(this.bracket.getDoubleAngleBracketString());
}
}
TypeScript では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.swift public class PrintQuotedBook : IPrint {
private var message:String
public init(_ message:String) {
self.message = message
}
public func printArticleName() {
print("「" + self.message + "」")
}
public func printBookName() {
print("『" + self.message + "』")
}
}
Main.swift let p:PrintQuotedBook = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
|
Adapterパターンを使用した例 PrintQuotedBook.swift public class PrintQuotedBook : Bracket, IPrint {
public override init(_ message:String) {
super.init(message)
}
public func printArticleName() {
print(getAngleBracketString())
}
public func printBookName() {
print(getDoubleAngleBracketString())
}
}
Main.swift let p:PrintQuotedBook = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.swift public class PrintQuotedBook : IPrint {
private var bracket:Bracket
public init(_ message:String) {
bracket = Bracket(message)
}
public func printArticleName() {
print(bracket.getAngleBracketString())
}
public func printBookName() {
print(bracket.getDoubleAngleBracketString())
}
}
Swift では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.kt class PrintQuotedBook(private val message: String) : IPrint {
override fun printArticleName() {
println("「${message}」")
}
override fun printBookName() {
println("『${message}』")
}
}
Main.kt fun main() {
val p = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
|
Adapterパターンを使用した例 PrintQuotedBook.kt class PrintQuotedBook(val message: String) : Bracket(message), IPrint {
override fun printArticleName() {
println(getAngleBracketString())
}
override fun printBookName() {
println(getDoubleAngleBracketString())
}
}
Main.kt fun main() {
val p = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.kt class PrintQuotedBook(val message: String) : IPrint {
private var bracket:Bracket = Bracket(message)
override fun printArticleName() {
println(bracket.getAngleBracketString())
}
override fun printBookName() {
println(bracket.getDoubleAngleBracketString())
}
}
Kotlin では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.scala class PrintQuotedBook(message: String) extends IPrint {
def printArticleName() {
System.out.println("「%s」".format(message))
def printBookName() {
System.out.println("『%s』".format(message))
}
Main.scala object Main {
def main(args: Array[String]) {
val p = PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
}
}
|
Adapterパターンを使用した例 PrintQuotedBook.scala class PrintQuotedBook(message: String) extends Bracket(message) with IPrint {
def printArticleName() {
System.out.println(getAngleBracketString())
}
def printBookName() {
System.out.println(getDoubleAngleBracketString())
}
}
Main.scala object Main {
def main(args: Array[String]) {
val p = new PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
}
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.scala class PrintQuotedBook(message: String) extends IPrint {
private val bracket: Bracket = new Bracket(message)
def printArticleName() {
System.out.println(bracket.getAngleBracketString())
}
def printBookName() {
System.out.println(bracket.getDoubleAngleBracketString())
}
}
Scala では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.groovy class PrintQuotedBook implements IPrint {
private String message
PrintQuotedBook(String message) {
this.message = message
}
void printArticleName() {
System.out.println("「" + message + "」")
}
void printBookName() {
System.out.println("『" + message + "』")
}
}
Main.groovy class Main {
static void main(String[] args) {
PrintQuotedBook p = new PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
}
}
|
Adapterパターンを使用した例 PrintQuotedBook.groovy class PrintQuotedBook extends Bracket implements IPrint {
PrintQuotedBook(String message) {
super(message)
}
void printArticleName() {
System.out.println(getAngleBracketString())
}
void printBookName() {
System.out.println(getDoubleAngleBracketString())
}
}
Main.groovy class Main {
static void main(String[] args) {
PrintQuotedBook p = new PrintQuotedBook("Hello")
p.printArticleName()
p.printBookName()
}
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.groovy class PrintQuotedBook implements IPrint {
private Bracket bracket
PrintQuotedBook(String message) {
bracket = new Bracket(message)
}
void printArticleName() {
System.out.println(bracket.getAngleBracketString())
}
void printBookName() {
System.out.println(bracket.getDoubleAngleBracketString())
}
}
Groovy では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.go import "fmt"
type PrintQuotedBook struct {
IPrint
message string
}
func (self *PrintQuotedBook) PrintArticleName() {
fmt.Println("「" + self.message + "」")
}
func (self *PrintQuotedBook) PrintBookName() {
fmt.Println("『" + self.message + "』")
}
func NewPrintQuotedBook(message string) *PrintQuotedBook {
return &PrintQuotedBook {
message: message,
}
}
Main.go func main() {
var p = NewPrintQuotedBook("Hello")
p.PrintArticleName()
p.PrintBookName()
}
|
Adapterパターンを使用した例 PrintQuotedBook.go import "fmt"
type PrintQuotedBook struct {
IPrint
*Bracket
}
func (self *PrintQuotedBook) PrintArticleName() {
fmt.Println(self.GetAngleBracketString())
}
func (self *PrintQuotedBook) PrintBookName() {
fmt.Println(self.GetDoubleAngleBracketString())
}
func NewPrintQuotedBook(message string) *PrintQuotedBook {
return &PrintQuotedBook {
Bracket: NewBracket(message),
}
}
Main.go func main() {
var p = NewPrintQuotedBook("Hello")
p.PrintArticleName()
p.PrintBookName()
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます(ただし、Go は、もともと継承がないため、移譲も大して変わりません)。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.go import "fmt"
type PrintQuotedBook struct {
IPrint
bracket *Bracket
}
func (self *PrintQuotedBook) PrintArticleName() {
fmt.Println(self.bracket.GetAngleBracketString())
}
func (self *PrintQuotedBook) PrintBookName() {
fmt.Println(self.bracket.GetDoubleAngleBracketString())
}
func NewPrintQuotedBook(message string) *PrintQuotedBook {
return &PrintQuotedBook {
bracket: NewBracket(message),
}
}
Go では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 printquotedbook.d import iprint;
public class PrintQuotedBook : IPrint {
private string message;
public this(string message) {
this.message = message;
}
public void printArticleName() {
printfln("「" + message + "」");
}
public void printBookName() {
printfln("『" + message + "』");
}
protected void printfln(T...)(T args) { // Shift JIS 出力
import std, std.windows.charset, core.vararg;
std.stdio.write(to!(string)(toMBSz(std.format.format(args))) ~ "\n");
}
}
main.d import printquotedbook;
int main() {
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
return 0;
}
|
Adapterパターンを使用した例 printquotedbook.d import bracket;
import iprint;
public class PrintQuotedBook : Bracket, IPrint {
public this(in string message) {
super(message);
}
public void printArticleName() {
printfln(getAngleBracketString());
}
public void printBookName() {
printfln(getDoubleAngleBracketString());
}
protected void printfln(T...)(T args) { // Shift JIS 出力
import std, std.windows.charset, core.vararg;
std.stdio.write(to!(string)(toMBSz(std.format.format(args))) ~ "\n");
}
}
main.d import printquotedbook;
public int main() {}
PrintQuotedBook p = new PrintQuotedBook("Hello");
p.printArticleName();
p.printBookName();
return 0;
}
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 printquotedbook.d import iprint;
import bracket;
public class PrintQuotedBook : IPrint {
private Bracket bracket;
public this(string message) {
bracket = new Bracket(message);
}
public void printArticleName() {
printfln(bracket.getAngleBracketString());
}
public void printBookName() {
printfln(bracket.getDoubleAngleBracketString());
}
private void printfln(T...)(T args) { // Shift JIS 出力
import std, std.windows.charset, core.vararg;
std.stdio.write(to!(string)(toMBSz(std.format.format(args))) ~ "\n");
}
}
D 言語では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
既存クラス、インタフェース
|
Adapterパターンを使用しない例 PrintQuotedBook.pas unit UnitPrintQuotedBook;
interface
uses
UnitIPrint;
type
PrintQuotedBook = class(TInterfacedObject, IPrint)
private
var message:string;
public
constructor Create(message:string);
procedure printArticleName();
procedure printBookName();
end;
implementation
constructor PrintQuotedBook.Create(message:string);
begin
self.message := message;
end;
procedure PrintQuotedBook.printArticleName();
begin
Writeln('「' + message + '」');
end;
procedure PrintQuotedBook.printBookName();
begin
Writeln('『' + message + '』');
end;
end.
Main.dpr program Main;
uses
System.SysUtils,
UnitBracket,
UnitIPrint,
UnitPrintQuotedBook;
var p:PrintQuotedBook;
begin
p := PrintQuotedBook.Create('Hello');
p.printArticleName();
p.printBookName();
p.Free;
end.
|
Adapterパターンを使用した例 PrintQuotedBook.pas unit UnitPrintQuotedBook;
interface
uses
UnitBracket,
UnitIPrint;
type
PrintQuotedBook = class(Bracket, IPrint)
public
constructor Ceate(message:string);
procedure printArticleName();
procedure printBookName();
function QueryInterface(const IID:TGUID; out Obj):HResult; stdcall;
function _AddRef:Integer; stdcall;
function _Release:Integer; stdcall;
end;
implementation
constructor PrintQuotedBook.Ceate(message: string);
begin
inherited Create(message);
end;
procedure PrintQuotedBook.printArticleName();
begin
Writeln(getAngleBracketString());
end;
procedure PrintQuotedBook.printBookName();
begin
Writeln(getDoubleAngleBracketString());
end;
function PrintQuotedBook.QueryInterface(const IID:TGUID; out Obj): HResult; stdcall;
begin
Result:=S_OK;
end;
function PrintQuotedBook._AddRef:Integer; stdcall;
begin
Result := 0;
end;
function PrintQuotedBook._Release:Integer; stdcall;
begin
Result := 0;
end;
end.
Main.dpr program AdapterGof;
uses
UnitPrintQuotedBook;
var p:PrintQuotedBook;
begin
p := PrintQuotedBook.Create('Hello');
p.printArticleName();
p.printBookName();
p.Free;
end.
|
|
同様の表示をする Bracket クラスがありますが使っていません。新たに同様な機能を作成しています。 簡単な処理ならこれでも良いかもしれませんが、少し複雑なものになると労力が無駄になりますし、果たして同じ処理なのかどうかも疑わしいこともあるでしょう。 |
ここでは、Bracket クラスを継承して、その中で定義されているメソッドを呼び出しています。 これなら、Bracket クラスが変更された場合でも、別途 PrintQuotedBook クラスで変更しなくても自動的に変更されることになります。 この例では継承を用いて実現しましたが、委譲(お任せ)を使って実現することもできます。 継承するのではなく、Bracket クラスのインスタンスを生成して、Bracket クラス内のメソッドを呼び出すわけです。 PrintQuotedBook.pas unit UnitPrintQuotedBook;
interface
uses
UnitBracket,
UnitIPrint;
type
PrintQuotedBook = class(TInterfacedObject, IPrint)
private
var _bracket:Bracket;
public
constructor Create(message:string);
procedure printArticleName();
procedure printBookName();
end;
implementation
constructor PrintQuotedBook.Create(message:string);
begin
_bracket := Bracket.Create(message);
end;
procedure PrintQuotedBook.printArticleName();
begin
Writeln(_bracket.getAngleBracketString());
end;
procedure PrintQuotedBook.printBookName();
begin
Writeln(_bracket.getDoubleAngleBracketString());
end;
end.
Delphi では、継承したスーパークラスのメソッドを隠蔽することはできません。先の例では、PrintQuotedBook を利用している main から Bracket のメソッドである getAngleBracketString() なども見えてしまうわけです。 しかし、後の例のような委譲にすれば PrintQuotedBook で定義したメソッドしか使用できません。 |
この例では、メソッドが大変小さいものですから、既存のクラスを再利用しなくても記述できます。しかし、その規模が大きく、かつ充分にテストされているとしたら再利用したいものです。Adapter パターンは、既存のクラスに一皮かぶせて必要とするクラスを作ります。