2010-12-02 10 views
0

以下のデザインはあなたによく見えますか?それはデザインパターンですか?リファクタリングが必要だと思うなら、それをどのように改善しますか?コードでこのデザインは意味がありますか?

 

public class FruitFetcher { 
    public static void main(String[] args) { 
     FruitFetcher fetcher = new FruitFetcher(); 
     Apple apple = (Apple) fetcher.fetch(new FetchAppleRequest()); 
    } 


    public Fruit fetch(FetchFruitRequest request){ 
     Fruit fruit = null; 

     if(request.getFruitName().equals(FetchAppleRequest.REQUEST_NAME)){ 
      fruit = new Apple(); 
     }else if (request.getFruitName().equals(FetchBananaRequest.REQUEST_NAME)){ 
      fruit = new Banana(); 
     } 
     return fruit; 
    } 

} 

abstract class FetchFruitRequest{ 

    abstract public String getFruitName(); 

} 

class FetchAppleRequest extends FetchFruitRequest{ 
    static String REQUEST_NAME = "Fetch_Apple"; 

    @Override 
    public String getFruitName() { 
     return REQUEST_NAME; 
    } 
} 

class FetchBananaRequest extends FetchFruitRequest{ 
    static String REQUEST_NAME = "Fetch_Banana"; 

    @Override 
    public String getFruitName() { 
     return REQUEST_NAME; 
    } 
} 

class Fruit { 
} 

class Apple extends Fruit{ 

} 

class Banana extends Fruit{ 

} 
 

FruitFetcherのクライアントが右のタイプにFruitをアップキャストする必要があり、あなたはそれが正しいことだと思いますか?


編集: エリート紳士の質問に答えるために、私はReqeustが単純な文字列以外の型が必要であることを示すために私のコードを変更しました。

PaymentServergetResponse()はまだ「醜い」のように見えますか?どのように私はそれを再調整するのですか?

 


public class PaymentServer { 


    public static void main(String[] args) { 
     PaymentServer server = new PaymentServer(); 
     //set pin 
     SetPinResponse setPinResponse = (SetPinResponse) server.getResponse(new SetPinRequest("aPin")); 
     System.out.println(setPinResponse.isSuccess()); 

     //make payment 
     MakePaymentResposne makePaymentResponse = (MakePaymentResposne) server.getResponse(new MakePaymentRequest(new Money("5.00)"),"aPin")); 
     System.out.println(makePaymentResponse.isSuccess()); 
    } 




    public Response getResponse(Request request){ 
     Response aResponse = null; 

     if(request.getRequestName().equals(SetPinRequest.REQUEST_NAME)){ 
      aResponse = new SetPinResponse(); 
     }else if (request.getRequestName().equals(MakePaymentRequest.REQUEST_NAME)){ 
      aResponse = new MakePaymentResposne(); 
     } 
     return aResponse; 
    } 

} 

abstract class Request{ 
    abstract public String getRequestName(); 
} 

class SetPinRequest extends Request{ 
    static String REQUEST_NAME = "Set_Pin"; 
    private String pin; 

    SetPinRequest(String pin){ 
    this.pin = pin; 
    } 

    @Override 
    public String getRequestName() { 
     return REQUEST_NAME; 
    } 

    boolean setPin(){ 
    //code to set pin 
    return true; 
    } 
} 

class MakePaymentRequest extends Request{ 
    static String REQUEST_NAME = "Make_Payment"; 
    private Money amount; 
    private String pin; 

    MakePayment(Money amount, String pin){ 
    this.amount = amount; 
    this.pin = pin; 
    } 

    @Override 
    public String getRequestName() { 
     return REQUEST_NAME; 
    } 
} 


abstract class Response { 
    abstract protected boolean isSuccess(); 

} 

class SetPinResponse extends Response{ 

    @Override 
    protected boolean isSuccess() { 
    return true; 
    } 

} 

class MakePaymentResposne extends Response{ 
    @Override 
    protected boolean isSuccess() { 
    return false; 
    } 

} 
 

おかげで、

サラ

+0

ありがとうございました編集のために – sarahTheButterFly

+1

宿題タグはなぜですか?Javaを学ぶための自己演習のようです。 –

+0

haha​​ ...宿題タグを追加しましたか?実際のプロジェクトを模擬するためにダミーのクラスを作った。 – sarahTheButterFly

答えて

3

あなたのデザインは、工場出荷時のパターンにかなり近いです。 「フェッチャー」はフルーツ工場で、あなたは特別なタイプのフルーツを求めて、そのフルーツを手に入れます。

「リクエスト」の部分は少し複雑に見えます。列挙型を使用することを検討してください:


public enum FruitType{ 
    APPLE, BANANA 
} 

public FruitFetcher { 
    public static Fruit fetch(FruitType type) { 
    switch(type) { 
     case APPLE: return new Apple(); 
     case BANANA: return new Banana(); 
    } 
    } 
    return null; 
} 

編集 - それはまだかなり複雑です。あなたが達成したいことを理解するにはしばらく時間がかかりますが、これは通常、より簡単な設計が必要であることを示す指標です。

まず - あなたRequestResponseクラスは抽象メソッド宣言しか提供しない場合、その後、あなたはインターフェイスとして、コードに両方の種類をあなたのコードをリファクタリングする必要があります。読みやすさを向上させるための一歩。

第2に、getResponseメソッドを大幅に簡略化することができます。あなたはその(醜い)のgetName構築体を必要としない - ちょうどrequestオブジェクトのタイプチェック:デザインパターンのほかに

public Response getResponse(Request request){ 
    Response aResponse = null; 

    if(request instanceof SetPinResponse) { 
     aResponse = new SetPinResponse((SetPinRequest) request); 
    } else if (request instanceof MakePaymentResposne) { 
     aResponse = new MakePaymentResposne((MakePaymentRequest) request); 
    } 

    return aResponse; 
} 
+0

あなたの返信Andreas_Dに感謝します。それは醜いですが、私はそれを感じましたが、それを再因子化する方法がわかりませんでした。多分それは全体的なデザインからです。皆さんに見てもらうためにここですべてのクラスを過ぎることはできませんが、少なくともリファクタリングが必要であるという確認を受けました。御時間ありがとうございます。 – sarahTheButterFly

-1

ヒント:これは...コードの "醜い" の部分である

if(request.getFruitName().equals(FetchAppleRequest.REQUEST_NAME)){ 
     fruit = new Apple(); 
    }else if (request.getFruitName().equals(FetchBananaRequest.REQUEST_NAME)){ 
     fruit = new Banana(); 
+3

これはどのように役立ちますか? –

1

を、あなたが探しているものGenericsです。

デザインパターンは、Factory Method Patternと呼ばれ、FruitFetcherは工場、Fruit(およびそのサブクラス)はプロダクトです。あなたのFruitFetcher.fetch


は(よりよい単語の欠乏のために)ビットの「曖昧」です。あなたが要求しているFruitを特定するtypeを渡すことをお勧めします。

type列挙型、整数、または文字列(それは本当にあなたがFruitFetcher.fetch()によって認識することができ、特定の値型を作成する方法に依存し

例になります。

public class FruitFetcher { 

    public Fruit fetch(String fruitName) { 
     if ("Apple".equals(fruitName)) { 
      return new Apple(); 
     } 

     if ("Banana".equals(fruitName)) { 
      return new Banana(); 
     } 

     return null; 
    } 
} 

これをnew FetchAppleRequest()またはnew FetchBananaRequest()よりも雄弁です。

+0

私はあなたが言っていることを理解しています。しかし、FetchAppleRequestにフルーツタイプだけが含まれる場合はどうですか?たぶん私の果物の例はここでは適していません。しかし、私が意味することは、フェッチのパラメータは単純なStringやenum以外の型である必要があるということです。 – sarahTheButterFly

+0

詳しく教えてください。複雑なタイプの人は、これらの複雑さを処理する[戦略パターン](http://en.wikipedia.org/wiki/Strategy_pattern)が必要です。 –

+0

投稿を編集しました。 – sarahTheButterFly

関連する問題