【问题标题】:MVC implementation/best-practices questionMVC 实现/最佳实践问题
【发布时间】:2010-04-15 21:15:15
【问题描述】:

我必须使用一些不是真正 MVC 的代码(即,它不使用显式框架等)。现在我们使用将数据传递给服务的 servlet。

这是我的问题。我收到一个 servlet 的帖子,其中包含我必须保存到数据库中的一大堆地址数据。数据(显然)在HttpServletRequest 对象中。我的问题是,如何将这些数据传递到服务中?我不愿意这样做:

AddressService.saveAddress(request);

因为我认为服务不应该依赖于请求。我的另一个选择是做这样的事情:

String addressLine = request.getParameter("addressLine");
..
.. about 7 other parameters
..
String zip = request.getParameter("zip");

AddressService.saveAddress(addressLine, ... 7 other parameters ..., zip);

但我也不喜欢有大量参数的函数。我正在考虑创建一个名为AddressData 的中间对象,它将保存来自请求的数据,然后将其传递给服务。这是一种可以接受的做事方式吗?

【问题讨论】:

    标签: model-view-controller design-patterns


    【解决方案1】:

    是的,这是消除这种依赖的一种已知方法。我想不起来确切的来源,但有几本书包含了这种技术。

    对此的一种变体是使AddressData 成为一个包装器,它不会复制和保存所有需要的请求数据,而是保留对它的私有引用并将所有调用转发给它。这可能更灵活、更简洁,尤其是在有很多请求参数和/或参数更改/频繁引入新参数的情况下。

    【讨论】:

      【解决方案2】:

      是的,这是一个有效的解决方案,称为Parameter Object

      【讨论】:

        【解决方案3】:

        使用接口解耦:

        型号:

        public interface Address {
            String getLine1();
            String getLine2();
            ...
            String getZip();
        }
        public class AddressBase implements Address {
            public AddressBase(String line1, String line2, ..., String zip) {
               ...
            }
            ...
        }
        public class AddressService {
            void saveAddress(Address address);
        }
        

        现在控制器有选项并且模型不受控制器实现的影响:

        控制器选项 1:

        // wrap - lazy interrogator
        class AddressRequestWrapper implements Address {
            ...
            AddressRequestWrapper(HttpRequest request) {
                this.request = request;
            }
            String getLine1() {   return request.get(LINE_1_FIELD_ID); }
            ...
        }
        

        控制器选项 2:

        // "wrap" - eager interrogator
        class AddressRequestWrapper extends AddressBase {
            AddressRequestWrapper(HttpRequest request) {
                super(
                    request.get(LINE_1_FIELD_ID),
                    request.get(LINE_2_FIELD_ID),
                    ...
                    request.get(ZIP_FIELD_ID)
                );
          }
          ...
        }
        

        控制器选项 3:

        // Just use AddressBase directly
        Address address =
            new AddressBase(
                    request.get(LINE_1_FIELD_ID),
                    request.get(LINE_2_FIELD_ID),
                    ...
                    request.get(ZIP_FIELD_ID)
            );
        AddressService.saveAddress(address);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-02-04
          • 1970-01-01
          • 2015-09-11
          • 1970-01-01
          • 2018-02-25
          • 1970-01-01
          相关资源
          最近更新 更多