为了账号安全,请及时绑定邮箱和手机立即绑定

使用模式在 Java 中重复代码重构

使用模式在 Java 中重复代码重构

蛊毒传说 2022-05-21 21:01:00
这更多是关于 Java 而不是 Dropwizard;但我在 Dropwizard 中有两个资源: CustomerResource和ApiResource.有CustomerResource一种createCustomer方法基本上可以创建一个新客户。当ApiResource第三方调用其中的方法时,它也会创建一个新客户,所以这让我想到了重复代码和解决它的最佳方法。我有几种方法;但首先这里是为了更清晰的类。@Path("/internal")        public class CustomerResource{    private DBDao dbDao;    private AnotherAPI api;    //constructor for DI    public Response Create(@internalAuth CustomerPojo customerPojo) {        //logic to validate customerpojo        //logic to ensure user isn't a duplicate        //some other validation logic        //finally user creation/saving to DB        Return response.ok(200).build();    }}@Path("/external")public class ApiResource{    private DBDao dbDao;    private AnotherAPI api;    //constructor for DI    public Response Create(@ExternalAuth PartialCustomerPojo partialCustomerPojo) {        //logic to validate PartialCustomerpojo        //supplement partialCustomerPojo        //logic to ensure user isn't a duplicate        //some other validation logic        //finally user creation/saving to DB        Return response.ok(200).build();    }}因此,两个主要区别是端点的调用方式(身份验证)和提供的有效负载。我考虑删除重复代码的方法是创建一个新的具体类,该类从两个资源中获取共性,并且每个资源都实例化一个像这样的新类。public class CommonClass{    private DBDao dbDao;    private AnotherAPI api;    //constructor for DI    public boolean Create (CommonPojo commonPojo) {        //logic to validate customerPojo        //logic to ensure user isn't a duplicate        //some other validation logic        //finally user creation/saving to DB        Return response.ok(200).build();    }}现在在里面CustomerResource,ApiResource我只是这样做。CommonClass commonClass = new CommonClass(dbDao, api);//create a new instance customerPojo or CommonPojo and call commonClass.create(customerPojo);这听起来像是一个好策略吗?除了重复之外,还有其他问题吗?这两个资源方法也不能在同一个类中。任何最佳实践将不胜感激。
查看完整描述

3 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

我认为继承不是最好的解决方案。我也认为构图要好得多。这可以帮助您使用通用代码并在需要更改功能的其他地方轻松更改它。


此外,它还允许您更轻松地测试所有类。


例如:


class CommonPojo {}

class CustomerPojo extends CommonPojo {}

class PartialCustomerPojo extends CommonPojo {}


interface IResourceValid {

    boolean isResourceValid(CommonPojo pojo);

}


class CustomerPojoValidator implements IResourceValid {

    @Override

    public boolean isResourceValid(CommonPojo pojo) {

        //your validation for customer

        return false;

    }

}


class PartialCustomerPojoValidator implements IResourceValid {

    @Override

    public boolean isResourceValid(CommonPojo pojo) {

        //your validation for partial customer

        return true;

    }

}


class CommonResource{

    private DBDao dbDao;

    private AnotherAPI api;

    private IResourceValid validator;


    public IResourceValid getValidator() {

        return validator;

    }


    //constructor for DI


    public Response Create(CommonPojo commonPojo) {

        //logic to validate customerpojo

        //logic to ensure user isn't a duplicate

        //some other validation logic

        //finally user creation/saving to DB

        validator.isResourceValid(commonPojo);

        return response.ok(200).build();

    }

}


//@Path("/internal")

class CustomerResource{

    private CommonResource resource;


    //constructor for DI


    public Response Create(CustomerPojo CustomerPojo) {

        return resource.Create(CustomerPojo);

    }

}


//@Path("/external")

class ApiResource{

    private CommonResource resource;


    //constructor for DI


    public Response Create(PartialCustomerPojo partialCustomerPojo) {

        return resource.Create(partialCustomerPojo);

    }

}


DBDao dao = new DBDao();

AnotherAPI api = new AnotherAPI();


CommonResource castomerCreator = new CommonResource(new CustomerPojoValidator(), dao, api);

CommonResource apiCreator = new CommonResource(new PartialCustomerPojoValidator(), dao, api);


CustomerResource customerResource = new CustomerResource(castomerCreator);

ApiResource apiResource = new ApiResource(apiCreator);


customerResource.Create(somePojo);

apiResource.Create(someAnotherPojo);


查看完整回答
反对 回复 2022-05-21
?
噜噜哒

TA贡献1784条经验 获得超7个赞

这可以通过以下两种方式来实现

  1. 创建一个接口,然后在两个目标类上实现,以便它们都可以提供本地实现

  2. 使用抽象类,然后扩展它。

接口不会使您免于编码,而是使抽象类不强制执行任何操作的情况下保持内联,因此两者都有弱点。您可以实现多个接口,但只能扩展一个类。牢记这一点,我更倾向于接口

从 Java 8 开始。Java 支持使用接口的默认方法,我认为这是最好的方法。您可以在默认方法中提供默认实现,用户可以根据需要覆盖该方法。这将为您提供最好的接口和抽象类。

public interface CommonCode {


    default public boolean create(CommonPojo commonPojo) {

        //logic to validate customerPojo

        //logic to ensure user isn't a duplicate

        //some other validation logic

        //finally user creation/saving to DB

        Return response.ok(200).build();

    }

}


@Path("/internal")        

public class CustomerResource  implements CommonCode {

    private DBDao dbDao;

    private AnotherAPI api;


    //constructor for DI

    create(CommonPojo)

}


@Path("/external")

public class ApiResource implements CommonCode {

    private DBDao dbDao;

    private AnotherAPI api;


    //constructor for DI

    create(CommonPojo)

}


查看完整回答
反对 回复 2022-05-21
?
当年话下

TA贡献1890条经验 获得超9个赞

有很多选择,这完全取决于您使用的策略。我更喜欢使用抽象类并在其中制作非抽象方法。当您扩展抽象类时,您可以选择要使用的方法。在您的场景中,它应该如下所示:


public abstract class AbstractResource {


    private CustomerService customerService;


    @Autowired

    public void setCustomerService(CustomerService customerService) {

        this.customerService = customerService;

    }


    public Response create(CustomerPojo customer) {

        return customerService.createCustomerPojo(customer);

    }


    public Response create(PartialCustomerPojo customer) {

        return customerService.createPartialCustomerPojo(customer);

    }


}

CustomerResource @Override唯一需要的方法:


@Path("/internal")

@Component

public class CustomerResource extends AbstractResource {


    @POST

    @Override

    public Response create(PartialCustomerPojo customer) {

        return super.create(customer);

    }


}

相同的ApiResource


@Path("/external")

@Component

public class ApiResource extends AbstractResource {


    @POST

    @Override

    public Response create(CustomerPojo customer) {

        return super.create(customer);

    }


}

一切都在一个地方 - CustomerService,在那里你做你的逻辑。


@Service

public class CustomerService {


    @Autowired

    private AnotherAPI api;


    @Autowired

    private DBDao dao;


    public Response createCustomerPojo(CustomerPojo customer) {

        //logic to validate customerpojo

        //logic to ensure user isn't a duplicate

        //some other validation logic

        //finally user creation/saving to DB

    }


    public Response createPartialCustomerPojo(PartialCustomerPojo customer) {

        //logic to validate PartialCustomerpojo

        //supplement partialCustomerPojo

        //logic to ensure user isn't a duplicate

        //some other validation logic

        //finally user creation/saving to DB

    }

}

如果要最小化重复,则必须使用接口并在每个类中实现:


public class CustomerPojo implements PojoInterface {

}

public class PartialCustomerPojo implements PojoInterface {

}

现在你只能有一个抽象方法:


public abstract class AbstractResource {


    private CustomerService customerService;


    @Autowired

    public void setCustomerService(CustomerService customerService) {

        this.customerService = customerService;

    }


    public abstract Response create(PojoInterface customer);


}

然后在“一个地方”,您需要检查参数的每个实例:


public Response create(PojoInterface customer) {

        if (customer instanceof CustomerPojo){

            //logic to validate customerpojo

            //logic to ensure user isn't a duplicate

            //some other validation logic

            //finally user creation/saving to DB

        }else if (customer instanceof PartialCustomerPojo){

            //logic to validate PartialCustomerpojo

            //supplement partialCustomerPojo

            //logic to ensure user isn't a duplicate

            //some other validation logic

            //finally user creation/saving to DB

        }

    }

编辑:对不起,很长的帖子......


查看完整回答
反对 回复 2022-05-21
  • 3 回答
  • 0 关注
  • 120 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信