HeadFirstデザインモードを読む(一)
最近デザインモードのものを見ていますので、今日は以前見たHeadFirstデザインモードの資料を取り出してみました。 今日のまとめで、これから更新します。
これから:
情景1:
今はアヒルには二つの種類があります。MallardDuck、RedheadDuckはみんなおぎゃあと叫んで、泳いでいますが、外観は違います。コードの設計は以下の通りです。
アヒルの基質(ダクト)
私たちはダクト類に直接fly()の方法を追加して、アヒルは全部飛んでしまいます。
今のダクトのコードは以下の通りです。
アヒルの新しい種類を追加します。RubberDuck(アヒルの消しゴム):
まずflyとquackをそれぞれ二つの違うインターフェースを作りましょう。
Flayable
この時、あなたはデザインモードを期待してあなたを救うかもしれません。
この段階で、設計モデルの第一原則を見ました。
これらの「変化しない部分」を、「fly()」と「quack()」に分けます。
「おぎゃあ」インターフェース:QuackBehavior
上では第三の設計原則も認識させられました。
これから:
情景1:
今はアヒルには二つの種類があります。MallardDuck、RedheadDuckはみんなおぎゃあと叫んで、泳いでいますが、外観は違います。コードの設計は以下の通りです。
アヒルの基質(ダクト)
public abstract class Duck {
public void quack(){
System.out.println(" !");
}
public void swim(){
System.out.println(" !");
}
public abstract void display();
}
赤頭鴨(RedheadDuck)public class RedheadDuck extends Duck {
@Override
public void display() {
System.out.println(" !");
}
}
鴨(MallardDuck)public class MallardDuck extends Duck {
@Override
public void display() {
System.out.println(" !");
}
}
今は状況が少し変わりました。アヒルをflyできるようにします。私たちはダクト類に直接fly()の方法を追加して、アヒルは全部飛んでしまいます。
今のダクトのコードは以下の通りです。
public abstract class Duck {
public void quack(){
System.out.println(" !");
}
public void swim(){
System.out.println(" !");
}
public abstract void display();
public void fly(){
System.out.println(" !");
}
ここで一つのことを見落としました。アヒルが全部飛んでいるわけではないです。アヒルの新しい種類を追加します。RubberDuck(アヒルの消しゴム):
public class RubberDuck extends Duck {
@Override
public void quack() {
System.out.println(" !");
}
@Override
public void fly() {
// ,
}
@Override
public void display() {
System.out.println(" !");
}
}
このように見れば、一時的に満足できます。アヒルの消しゴムの「需要」が、もし私が新しいアヒルを追加したら、どうすればいいですか?まずflyとquackをそれぞれ二つの違うインターフェースを作りましょう。
Flayable
public interface Flyable {
void fly();
}
Quabalepublic interface Quackable {
void quack();
}
このように、flyがあれば、quackのアヒルはこの二つのインターフェースを実現しますが、新しい問題が現れました。これはいくつかの問題を解決しましたが、コードを多重化することができません。この時、あなたはデザインモードを期待してあなたを救うかもしれません。
この段階で、設計モデルの第一原則を見ました。
, , 。
現在知っているように、Duckはfly()、quack()の問題以外は正常です。これらの「変化しない部分」を、「fly()」と「quack()」に分けます。
「おぎゃあ」インターフェース:QuackBehavior
public interface QuackBehavior {
void quack();
}
Quck(デフォルトの呼び方)public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println(" !");
}
}
スクエア(ガモの呼び方)public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println(" !");
}
}
MuteQuck(アヒルのハスキー)public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
// , !
}
}
「飛」のインターフェース:FlyBehavirpublic interface FlyBehavior {
void fly();
}
FlyNoWay(飛べない)public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
// , !
}
}
FlyWithwings(翼で飛ぶ)public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println(" !");
}
}
最後に私達のダクトは次のようになりました。public abstract class Duck {
private FlyBehavior flyBehavior;
private QuackBehavior quackBehavior;
public void swim(){
System.out.println(" !");
}
public void performQuack(){
quackBehavior.quack();
}
public void performFly(){
flyBehavior.fly();
}
public abstract void display();
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
PS:上記では第二の設計原則を認識しました。 , !
インターフェースは本当のインターフェースではなく、多状態であることが鍵です。スーパークラスのプログラミングに対しても理解できます。このように書く必要はなく、運行中に実際の状況によって本当の行動、方法を実行することができます。上では第三の設計原則も認識させられました。
, !
テストコード:Duck duck = new RubberDuck();
duck.setFlyBehavior(new FlyNoWay());
duck.performFly();
上記の例は、実際にはデザインモードのポリシーモードを使用しています。