【问题标题】:Inheritance and REST API Controllers - Dealing with Subclasses继承和 REST API 控制器 - 处理子类
【发布时间】:2018-11-14 05:51:01
【问题描述】:

我正在开发以下优惠券和优惠平台的类层次结构::

Promotion - abstract
 - Coupon
 - Sale
 - Deal

(CouponSaleDeal 继承自 Promotion。Promotion 有一个名为 type 的字符串属性和一个用于初始化子类的类型属性为字符串值。例如优惠券中的type 获取值“优惠券”等...)

对于每个子类,我都有一个 DAOService 类,例如 CouponDAOCouponService 等。

在前端用户可以通过Angular 2界面创建CouponSaleDeal等我决定使用以下控制器:

PromotionController - abstract
 - CouponController
 - SaleController
 - DealController

CouponControllerSaleControllerDealController继承自PromotionController

PromotionController 将包含所有子类共有的所有通用 CRUD 函数,并且在特定控制器中,我将处理针对这些类的特定操作。

A) 现在面临的问题是如何实例化来自客户端的正确对象。例如,当用户提交 CouponSaleDeal 时,我如何实例化正确的对象。例如在 PromotionController 我有这样的功能::

@RequestMapping(value=CREATE_PROMO, method=RequestMethod.POST)
    public ResponseEntity<?> create(@RequestBody Promotion promotion){
        promotionService.save(promotion);
        return new ResponseEntity<>("", HttpStatus.OK); 
    }

Promotion 是抽象的,是函数的参数。我应该使用工厂模式和**type** 属性来创建正确的对象吗? 例如,如果 type="Coupon" 则创建 Coupon 对象,如果是 "Sale" 则创建 Sale 对象

B) 由于控制器使用服务对象,这意味着我必须在 PromotionController 中声明所有三个服务对象。因为在实例化了正确的对象之后,我需要调用其对应的服务来完成这项工作。在上面的方法中,我有promotionService,我认为应该用正确的子类服务替换

C) 我正在寻找如何处理处理现实世界中子类的 REST API,就像我上面描述的情况一样

D) 我想通过将所有 CRUD 操作复制到它们的特定控制器来简化自己的工作,但似乎这将是重复的代码。

我认为有更好的方法可以做到。

如果我能找到一个处理这种情况的开源项目,我也尝试过,但似乎我发现的所有项目都使用一个类而不是继承。他们的 REST/API 不处理继承情况

【问题讨论】:

  • 首先,我不建议您使用抽象的@Controller,因为@Controller 是通过端点进入应用程序的入口。如果一个端点调用 2 个或更多控制器,这可能会导致一些麻烦。

标签: java spring rest spring-mvc spring-boot


【解决方案1】:

回答你(A),我认为你可以使用 requestObject.instanceOf() 方法,告诉正确的子类类型,然后用正确的处理程序处理。

【讨论】:

    【解决方案2】:

    在我看来,让您的端点保持简单。从 REST API 的角度来看,创建单个或仅一个控制器,并在控制器层之后使用以下模式。据我所知,最好让 REST 端点远离继承/重用,并在接收和验证请求后应用它。

    要从控制器实例化服务/帮助层,请使用工厂方法模式:

    https://en.wikipedia.org/wiki/Factory_method_pattern

    创建一个 PromotionServiceFactory,它根据促销类型返回 PromotionService 实现。

    在控制器中,使用工厂调用相应的推广服务方法。工厂仍然接受 Promotion 类型的参数。

    @RequestMapping(value=CREATE_COUPON, method=RequestMethod.POST)
        public ResponseEntity<?> create(@RequestBody Promotion promotion){
    //helper if adding one more helper layer. The factory invocation is then //transferred to the helper layer
      PromotionService couponService = promotionServiceFactory.get(PROMOTYPES.COUPON);
    couponService.save(promotion);
            return new ResponseEntity<>("", HttpStatus.OK); 
        }
    

    从您的问题来看,似乎有针对不同促销类型的常见 CRUD/其他方法。如果每个促销的某些步骤/子任务相同,而其他的则不同,则这是服务层中模板模式的一个很好的候选者。否则,您可以通过创建抽象提升服务来存储常见的 CRUD 方法。

    https://en.wikipedia.org/wiki/Template_method_pattern

    使用主要方法和常见 CRUD 方法的实现创建一个抽象提升服务。使用各自不同的方法创建其他促销服务类型的单独实现。

    【讨论】:

      【解决方案3】:

      我认为您可以根据逻辑以两种方式处理此问题。 如果您想将所有内容分开,请为优惠券/交易/销售创建不同的端点。这样每个端点都会调用它的控制器等等。

      2) 如果您认为代码相同,您可以使用抽象工厂模式来实例化正确的服务和 DAO 对象。

      这完全取决于您的业务需求,如果代码逻辑几乎相同,我更喜欢第二种方式。每个继承一个控制器,因此如果将来层次结构增加,您不需要创建多个类,直到需要。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-14
        • 1970-01-01
        相关资源
        最近更新 更多