如何避免在没有继承的情况下重复使用DTOs?

huangapple go评论64阅读模式
英文:

How can I avoid DTOs duplication without inheritance?

问题

我正在与许多社交网络进行连接,以便在我的应用程序中进行登录。
我为每个社交网络响应都有一个DTO。

public class GoogleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private AgeRange ageRange;
    // 更多特定字段
}

public class FacebookUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private String picture;
    // 更多特定字段
}

public class AppleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private Boolean emailVerified;
    // 更多特定字段
}

在每个社交网络连接器中,我执行类似的步骤来获取信息,因此我认为可以使用以下DTO:

public class SocialNetworkInfo {
    protected String id;
    protected String firstName;
    protected String lastName;
    protected String email;
}

社交网络的DTO可以扩展此DTO以获取共同字段。然后,我可以使用这个通用DTO来实现一个抽象连接器,处理连接器之间的所有重复逻辑(发出请求,解析响应等):

abstract class AbstractConnector {
    abstract SocialNetworkInfo fetchUserInfo(String networkId);
    ...
}

但我意识到在上述情况下,我在服务层中需要那些特定字段来进行一些更改和操作。

SocialNetworkInfo networkUserInfo = facebookConnector.fetchUserInfo(facebookId);
facebookService.updatePicture(networkUserInfo.getPicture()); // 无法访问此特定字段

你认为在不进行强制转换并避免逻辑或DTO重复的情况下,应该采取哪种最佳方法来处理这种情况?

很想听听你的想法。

谢谢!

英文:

I am connecting with many social networks for login in my application.
I have one DTO for each social network response.

public class GoogleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private AgeRange ageRange;
    // more specific fields
}

public class FacebookUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private String picture;
    // more specific fields
}

public class AppleUserInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
    private Boolean emailVerified;
    // more specific fields
}

In each social network connector, I make similar steps to fetch the information, so I thought I could go with some DTO as follows:

public class SocialNetworkInfo {
    protected String id;
    protected String firstName;
    protected String lastName;
    protected String email;
}

Social networks DTOs could extend this to obtain the common fields. Then I could use this generic DTO to implement an abstract connector that deals with all the duplicate logic between connectors (make request, parse response, etc...):

abstract class AbstractConnector {
    abstract SocialNetworkInfo fetchUserInfo(String networkId);
    ...
}

But I realized that above, in my service layer, I would need those specific fields to make some changes and operations.

SocialNetworkInfo networkUserInfo = facebookConnector.fetchUserInfo(facebookId);
facebookService.updatePicture(networkUserInfo.getPicture()); // can't access this specific field

What do you think that's the best way to go through this situation without casting and avoiding logic or DTO duplication?

Would love to hear your thoughts.

Thanks!

答案1

得分: 2

根据您的情况,所有社交网络模型具有相同的性质,因此如果您将共同属性移动到名为 CommonSocialInfo 的共享类中,那是可以的。接下来,我建议为连接器提供接口,如下所示:

interface SocialNetworkConnector<T extends SocialNetworkInfo> {
    T fetchUserInfo(String userId);
}

当然,为了共同功能(对于连接器),定义一个实现上述接口的共同抽象类是个很好的想法(实现模板模式)。我看到您正在单独使用 FacebookService 及其相关连接器。在这种情况下,我认为使用组合是个好主意,使得 SocialNetworkService 依赖于其连接器。简而言之,FacebookService 依赖于 FacebookConnector,以此类推。以下是一个快速示例:

public class FacebookService implements SocialNetworkService {
    private final SocialNetworkConnector<FacebookSocialInfo> connector;
    ...
}

如果您需要实现多个社交服务,您可以使用工厂模式来生成所需的服务,以下是一个快速示例:

interface SocialNetworkServiceFactory {
    SocialNetworkService getFacebookService();
    ...
}

如果您需要更详细的帮助,或者对这些想法有疑问 - 请随时提问!

英文:

According to your situation, all social network models have the same nature, so it's ok if you move common attributes to shared class like CommonSocialInfo. Then I would recommend to provide interface for the connectors like:

interface SocialNetworkConnector&lt;T extends SocialNetworkInfo&gt; {
    T fetchUserInfo(String userId);
}

Of course for common functionality(for connectors) is great idea to define common abstract class that implements interface above (implement Template pattern). I see that you are using FacebookService and related connector separately. I think that good idea to use composition in this case and make SocialNetworkService dependent on it connector. In short, FacebookService depends on FacebookConnecter and so on. Just a quick example:

public class FacebookService implements SocialNetworkService {
    private final SocialNetworkConnector&lt;FacebookSocialInfo&gt; connector;
    ...
}  

And if you need to implement multiple social service, you can use Factory pattern to produce required service, quick example:

interface SocialNetworkServiceFactory {
    SocialNetworkService getFacebookService();
    ...
}

If you need more detailed help or you have troubles with understanding of the idea - feel free to ask!

答案2

得分: 2

如果您不想使用继承,我建议考虑组合。代码可以如下所示:

public class SocialNetworkInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
}

public class GoogleUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private AgeRange ageRange;
    // 更多特定字段
}

public class FacebookUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private String picture;
    // 更多特定字段
}

public class AppleUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private Boolean emailVerified;
    // 更多特定字段
}
英文:

If you don't want to use inheritance, I'd suggest to consider composition. The code can look as follows:

public class SocialNetworkInfo {
    private String id;
    private String firstName;
    private String lastName;
    private String email;
}

public class GoogleUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private AgeRange ageRange;
    // more specific fields
}

public class FacebookUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private String picture;
    // more specific fields
}

public class AppleUserInfo {
    private SocialNetworkInfo socialNetworkInfo;
    private Boolean emailVerified;
    // more specific fields
}

huangapple
  • 本文由 发表于 2020年5月29日 06:36:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/62075666.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定