Factory Method パターン
簡単にいうと、オブジェクトの生成を new 演算子を使わずに メソッドで行うパターンです。これは、インタフェースを使うことで実現できます。
次の2つのjavaファイルを作成してください。
RacerFactory.java
interface Racer{
void accel();
}
abstract class FAIRLADY {
String engine;
abstract void Engine();
FAIRLADY(){
maker();
Engine();
}
void maker(){
System.out.println("日産です");
}
public void accel(){
System.out.println(this.engine+" 全開だぜ!");
}
}
class S30 extends FAIRLADY{
void Engine(){
this.engine="直列6気筒のL型エンジン";
}
}
class Z33 extends FAIRLADY implements Racer{
void Engine(){
this.engine= "V6エンジン";
}
}
abstract class SKYLINE {
String engine;
String name;
abstract void Engine();
abstract void Name();
SKYLINE(){
Name();
System.out.println("私の名前は"+ this.name);
Engine();
Taillamp();
}
void Taillamp(){
System.out.println("丸いランプが特徴です");
}
public void accel(){
System.out.println(this.engine+" バリバリだぜ");
}
}
class GTR extends SKYLINE implements Racer{
void Name(){
this.name="GTR";
}
void Engine(){
this.engine="ターボエンジン搭載";
}
}
class V35 extends SKYLINE{
void Name(){
this.name="V35";
}
public void Engine(){
this.engine="VQ30DD型エンジン";
}
void Taillamp(){
System.out.println("丸いランプが廃止されました");
}
}
public class RacerFactory{
Racer makeCar(String carname){
if(carname.equals("GTR")){
return new GTR();
}
else if(carname.equals("Z33")){
return new Z33();
}
else{
return null ;
}
}
}
Factorysample.java
public class Factorysample {
public static void main(String[] args) {
RacerFactory rf = new RacerFactory();
Racer r = rf.makeCar("GTR");
r.accel();
r = rf.makeCar("Z33");
r.accel();
}
}
入力したら、Factorysample.javaを実行してください。さて、このパターンは何が特徴があるのでしょうか?
FactoryMethodパターンでは、
- クラスを利用する側で newを記述していない
- インタフェース(またはスーパークラス)で受け取っている
という特徴があります。この意義はなにか?今回、2つのファイルに分けたことに意味があります。この2つのファイルはそれぞれ違うプログラマーが作っているということを想像してみてください。両者は、
- 車を作っている人(RacerFactory.java)
- 車を使う人(Factorysample.java)
という役割になります。車を使う人は、車(レーサー)を生成するクラス RacerFactoryというクラスを知っているだけでよいことになります。それらを呼び出すときにはプログラム内で newする必要はありません。
ここで言いたいことは、 new という演算子を使うということは、クラス間の依存性が高まってしまうということになります。もし、FactoryMethodパターンを使わずに、newで呼び出した場合と比較してみてください。
newで呼び出した場合
public class Factorysample {
public static void main(String[] args) {
Racer r = new GTR();
r.accel();
r = new Z33();
r.accel();
}
}
newを記述したことにより、このクラスは GTRクラスやZ33クラスと関係があるということを明示的に記述することになってしまいます。つまり、このクラスはGTRクラスやZ33クラスがないと動かないということです。
言い方をかえると、RacerFactoryクラスというのは、自動車メーカーです。
newで呼び出すということは、車種を指定してしまっているということです。つまり、Z33かGTRのみを受けつけるクラスということになります。
一方、RacerFactoryをnewするということは、メーカを指定しているということです。つまり、日産の生産するレーサーカーならなんでもいいよ。。ということです。
前者より後者のほうが依存性が少ないということがわかりますね?これは、近年非常に注目されているデザインパターンの1つです。「DI(Dependency Injection)」という言葉を調べてみてください。