这个设计有意义吗?

时间:2010-12-02 11:42:08

标签: java design-patterns

以下设计对您来说是否合适?这是一种设计模式吗?如果您认为需要重构,您会如何改进?


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转发为正确的类型,您认为这是正确的吗?


编辑: 为了回答The Elite Gentleman的问题,我修改了我的代码以表明Reqeust需要一个简单字符串以外的类型。

getResponse()中的PaymentServer仍然看起来有点'难看'吗?我如何重新审视它?



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;
    }

}

谢谢,

萨拉

3 个答案:

答案 0 :(得分:3)

您的设计非常接近工厂模式。 “fetcher”是一个水果工厂,你要求一种特殊类型的水果,并获得那种水果。

“请求”部分看起来有点复杂。考虑使用枚举:


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类只提供抽象方法声明,那么你应该将代码重构为接口两种类型的代码。提高可读性的一步。

第二 - getResponse方法可以大大简化。您不需要那个(丑陋的)getName构造 - 只需检查请求对象的类型:

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;
}

答案 1 :(得分:1)

除了设计模式之外,您正在寻找的是Generics

至于设计模式,你所做的是Factory Method Pattern,其中FruitFetcher是工厂,Fruit(及其子类)是产品。


你的FruitFetcher.fetch有点“含糊不清”(缺乏更好的词)。我建议传递type来识别您要求的Fruit

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()更有说服力。

答案 2 :(得分:-1)

提示:这是代码的“丑陋”部分......

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