Имеет ли этот дизайн смысл? - PullRequest
0 голосов
/ 02 декабря 2010

Вам понравился приведенный ниже дизайн?Это шаблон дизайна?Как бы вы улучшили его, если считаете, что он нуждается в рефакторинге?


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 нуждается в типе, отличном от простой строки.

Получает ли 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 ]

3 голосов
/ 02 декабря 2010

Ваш дизайн очень близок к заводскому образцу.«Сборщик» - это фруктовая фабрика, вы запрашиваете фрукт особого типа и получаете этот фрукт.

Часть «запрос» выглядит немного сложнее.Попробуйте использовать перечисления:


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

Редактировать - Это все еще довольно сложно.Требуется некоторое время, чтобы понять, чего вы хотите достичь, и обычно это показатель того, что должен быть более простой дизайн.

Первый - если ваши Request и Response классне предлагайте ничего, кроме абстрактных объявлений методов, тогда вы должны рефакторинг вашего кода, код обоих типов как интерфейсы.Один шаг к улучшению читабельности.

Второй - метод 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 голос
/ 02 декабря 2010

Помимо шаблона проектирования, вы ищете Generics .

Что касается шаблона проектирования, то, что вы делаете, называется Шаблон метода фабрики , где 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().

0 голосов
/ 02 декабря 2010

Подсказка: это «уродливая» часть кода ...

 if(request.getFruitName().equals(FetchAppleRequest.REQUEST_NAME)){
        fruit = new Apple();
    }else if (request.getFruitName().equals(FetchBananaRequest.REQUEST_NAME)){
        fruit =  new Banana();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...