簡體   English   中英

在Java中將類方法重構為接口

[英]Refactoring a class method to an interface in 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;

}

我重構的方式是這樣的:

我創建了一個名為EmailService的接口,該接口具有一個buildEmail()方法。 我在想,無論哪種實現這種方法的類都將以不同的方式構造/構建其電子郵件。

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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM