这样的设计有意义吗?

发布于 2024-10-05 19:18:25 字数 3440 浏览 1 评论 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 需要除简单字符串之外的类型。

PaymentServer 中的 get getResponse() 看起来仍然有点“丑陋”吗?我该如何重新编辑它?



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

}

谢谢,

莎拉

Does the below design look good to you? Is it a design pattern? How would you improve it if you think it needs refactoring?


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{

}

In the code, clients of FruitFetcher need to upcast Fruit to a right type, do you think that is correct?


Edit:
To answer The Elite Gentleman's question, I modified my code to show that the Reqeust needs a type other than a simple String.

Does get getResponse() in PaymentServer still look kind of 'ugly'? How do I re-fector it?



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

}

Thanks,

Sarah

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓝海似她心 2024-10-12 19:18:25

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

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


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

Your design is pretty close to a factory pattern. The "fetcher" is a fruit factory, you ask for a fruit of a special type and get that fruit.

The "request" part looks a bit complicated. Consider using enums:


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

Edit - It's still pretty complicated. It takes a while to understand, what you want to achieve and this is usually an indicator that there must be an easier design.

First - if your Request and Response classes offer nothing but abstract method declarations, then you should refactor your code an code both types as interfaces. One step towards improved readability.

Second - the getResponse methd can be greatly simplified. You don't need that (ugly) getName construct - just check the type of the request object:

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;
}
烟凡古楼 2024-10-12 19:18:25

除了设计模式之外,您还要寻找 泛型

至于设计模式,您所做的称为 工厂方法模式,其中 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() 更有说服力。

Besides the design pattern, what you're looking for is Generics.

As for design pattern, What you're doing is called the Factory Method Pattern, where FruitFetcher is the Factory and Fruit (and its subclasses) are Products.


Your FruitFetcher.fetch is a bit "ambiguous" (for the lack of better word). I would suggest passing a type that would identify the Fruit that you are requesting.

the type can be an enum, integer, or string (it really depends on how you want to create a specific value type that can be recognised by FruitFetcher.fetch().

Example:

public class FruitFetcher {

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

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

        return null;
    }
}

This is more eloquent than sending new FetchAppleRequest() or new FetchBananaRequest().

天气好吗我好吗 2024-10-12 19:18:25

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

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

Hint: this is the "ugly" part of the code...

 if(request.getFruitName().equals(FetchAppleRequest.REQUEST_NAME)){
        fruit = new Apple();
    }else if (request.getFruitName().equals(FetchBananaRequest.REQUEST_NAME)){
        fruit =  new Banana();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文