将类方法重构为java中的接口

问题描述:

在报告模块中,有一个电子邮件服务需要重构,因此我可以将其用作通用邮件服务。实际上,当他们想重置密码时,我有要求给用户发送电子邮件,这是重构的主要原因。将类方法重构为java中的接口

public class EmailService{ 

    public Email buildEmail(ReportRequest reportRequest){ 
    //build email using ReportRequest object here 
    } 

} 

@Builder 
@Getter 
@Setter 
@AllArgsConstructor 
public class Email implements Serializable { 
    private String subject; 
    private String text; 
    private String recipientEmail; 
    private String senderEmail; 

} 

的方式我不得不重构这是这样的:

我创建具有buildEmail()方法调用EmailService的接口。我在想,实现这个目标的任何一个类将有不同的方式来构建/构建它的电子邮件。

public interface EmailService{ 
    public Email buildEmail(); 
} 

public class ReportEmailService implements EmailService{ 
    public Email buildEmail(){} 
} 

public class PasswordEmailService implements EmailService{ 
    public Email buildEmail(){} 
} 

我现在的问题是,因为建筑的电子邮件将使用不同的对象(例如的ReportRequest或类似AccountInfo另一个对象),这将是传递所需的对象到buildEmail的最佳方式()?

我在这里做的是创建另一个方法,并为将在buildEmail()中使用的所需对象创建一个类变量。

基本上,现在它看起来像这样:

public class ReportEmailService implements EmailService{ 
    private ReportRequest reportRequest; 

    public void sendEmail(ReportRequest reportRequest){ 
     this.reportRequest = reportRequest; 
     Email email = buildEmail(); 
    } 

    public Email buildEmail(){ 
     #build email now using the report request object. 
    } 
} 

public class PasswordResetEmailService implements EmailService{ 
    private AccountInfo accountInfo; 

    public void sendEmail(AccountInfo accountInfo){ 
     this.accountInfo= accountInfo; 
     Email email = buildEmail(); 
    } 

    public Email buildEmail(){ 
     #build email now using the account info object. 
    } 
} 

我觉得我的做法是有点尴尬。在设计模式和重构方面,我可能已经错过了一些基本的东西,那么重构它最好的方法是什么?或者buildEmail()如何访问构建电子邮件时需要的特定对象。

泛型可以帮助你解决这个问题。

声明界面,如下所示:

interface EmailService<T> { 
    Email buildEmail(T t); 
} 

和你的实现是这样的:

class ReportEmailService<ReportRequest> implements EmailService { 
    Email buildEmail(ReportRequest req) { 
     ... 
    } 
} 

的“仿制药”的部分是什么,是人字形(<T>)之间,它作为一个占位符对于您稍后为每个实现定义的类型。

有关域驱动设计的书定义了服务是单例,所以在大多数情况下,您不应该创建同一服务的多个实例。

您可以实现多个电子邮件服务,也可以委托给参数。

interface EmailService { 
    boolean send(EmailFactory arg) 

    interface EmailFactory { 
     Email buildEmail(); 
    } 
} 

然后,你ReportRequestAccountInfo类可以实现EmailFactory,甚至更好,创建它知道如何buildEmail每种类型的适配器类...

class ReportRequestEmailFactory implements EmailFactory { 
    private ReportRequest report; 
    public Email buildEmail() { 
     return ... 
    } 
} 

class AccountInfoEmailFactory implements EmailFactory { 
    private AccountInfo account; 
    public Email buildEmail() { 
     return ... 
    } 
} 

这样你实施仅知道如何发送电子邮件的单个EmailService。并且您为每种您想要作为电子邮件发送的类型实现特定的包装器/适配器。

这也很容易扩展,以允许不同类型的电子邮件的不同类型的电子邮件,如FullDetailsAccountInfoEmailFactorySummaryAccountInfoEmailFactory

奖励积分,也许,如果你开始使用标准类型

class EmailService implements Consumer<Email> { 
    public void accept(Email email) { 
     // TODO: send email 
    } 
} 
class AccountInfoEmailTransformer implements Function<AccountInfo,Email> { 
    public Email apply(AccountInfo t) { 
     // TODO: transform AccountInfo to Email 
     return ... 
    } 
} 

然后,你可以做这样的事情

EmailService emailer = ... 
AccountInfoEmailFunction transformer = ... 

List<AccountInfo> accounts = ... 

accounts.stream().map(transformer).forEach(emailer);