第12 屆iT邦幫忙鐵人賽系列文章 (Day12)

這篇要來緩一下,做第一次的重構,寫到現在會發現 LineBotApp.cs 這個 class開始複雜了,程式碼越來越長,在OnMessageAsync.OnPostbackAsync 開始有相同的 Intent 重複定義

我們把取得 Intent 封裝成一個工廠

IIntentFactory.cs 定義一個工廠介面

    public interface IIntentFactory

    {

    IReplyIntent GetIntent(string intentName, string userId);

    }

IntentFactory.cs 實作這個介面

    public class IntentFactory : IIntentFactory

    {

    private readonly LineReplyMessageUtility lineMessageUtility;

    private readonly LineProfileUtility lineProfileUtility;

    public IntentFactory(LineReplyMessageUtility _lineMessageUtility, LineProfileUtility _lineProfileUtility)

    {

    lineMessageUtility = _lineMessageUtility;

    lineProfileUtility = _lineProfileUtility;

    }

    public IReplyIntent GetIntent(string intentName, string userId)

    {

    var intents = new Dictionary<string, IReplyIntent>()

    {

    { "Welcome" , new Welcome(lineMessageUtility,lineProfileUtility,userId)},

    { "電子喜帖" , new WeddingInvitationFromImage(lineMessageUtility,lineProfileUtility)},

    { "電子喜帖(FlexMsg)" , new WeddingInvitation(lineMessageUtility,lineProfileUtility)},

    { "前導影片" , new WeddingTrailer(lineMessageUtility,lineProfileUtility)},

    { "婚宴地點" , new WeddingLocation(lineMessageUtility,lineProfileUtility)},

    { "婚紗輪播" , new PhotoCarousel(lineMessageUtility,lineProfileUtility)},

    { "交通資訊" , new Directions(lineMessageUtility,lineProfileUtility)},

    { "從高鐵" , new DefaultIntent(lineMessageUtility,lineProfileUtility,"至 北門站 搭乘松山新店線至 南京復興站 步行7分鐘")},

    { "從捷運" , new DefaultIntent(lineMessageUtility,lineProfileUtility,"捷運台北小巨蛋站6分鐘/南京復興站只需7分鐘")},

    { "從機場" , new DefaultIntent(lineMessageUtility,lineProfileUtility,"酒店距離松山國際機場僅 5 分鐘車程")},

    { "停車資訊" , new DefaultIntent(lineMessageUtility,lineProfileUtility,"酒店的停車場為室內停車場,位於B5及B6")},

    { "開車提醒" , new DefaultIntent(lineMessageUtility,lineProfileUtility,"? 當天有紅酒享用,切記開車不喝酒,快快樂樂平平安安的回家~ ?")},

    { "Default" ,new DefaultIntent(lineMessageUtility,lineProfileUtility)},

    };

    return intents.ContainsKey(intentName) ? intents[intentName] : intents["Default"];

    }

    }

LinebotApp.cs 注入IIntentFactory,原本的 lineMessageUtility.lineProfileUtility 職責改由工廠裡面使用,LineBotApp 不再處理回覆的職責,這邊也不需要注入了

記得要在 Startup.cs 注入

LineBotApp.cs 重構後

這樣就乾淨多了,也不用相同的 intent 重複寫了兩次,重構到這篇,覺得還夠用,之後實作開始複雜我們再來繼續重構

    protected virtual async Task OnMessageAsync(Event ev)

    {

    if (ev.message.Type.Equals(LineMessageType.text))

    {

    var intent = intentFactory.GetIntent(ev.message.Text, ev.source.userId);

    await intent.ReplyAsync(ev.replyToken);

    }

    }

    protected virtual async Task OnFollowAsync(Event ev)

    {

    var intent = intentFactory.GetIntent(intentName: "Welcome", ev.source.userId);

    await intent.ReplyAsync(ev.replyToken);

    }

    protected virtual async Task OnUnfollowAsync(Event ev)

    {

    // 可以記錄誰封鎖了這個Bot

    await Task.CompletedTask;

    }

    protected virtual async Task OnUnPostbackAsync(Event ev)

    {

    var intent = intentFactory.GetIntent(ev.postback.data, ev.source.userId);

    await intent.ReplyAsync(ev.replyToken);

    }

懶人包,本次學到了什麼?