iT邦幫忙

2024 iThome 鐵人賽

DAY 18
0

介紹

Android 開發者肯定對觀察者模式不陌生,從早期的 EventBus 到後期的 RxJava,都是觀察者模式的應用
開發上要注意的是在生命週期開始的時候建立觀察,生命週期結束時取消觀察
如果忘了取消觀察,就會出現梗圖

五黑男一白女,jpg

觀察者模式實作

觀察者模式是由兩個元件組成

  1. 觀察者(Observer)
  2. 被觀察者(Subject)

這次一樣建立會員系統,觀察使用者註冊會員時資料填寫是否填寫完整

  1. 建立會員系統觀察者
public abstract class MemberObserver {

    private String name;

    protected MemberObserver(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract String getRegister(boolean isRegister);
}
  1. 建立全家使用者,繼承會員系統觀察者
public class FamilyMark extends MemberObserver {

    public FamilyMark(String name) {
        super(name);
    }

    @Override
    public String getRegister(boolean isRegister) {
        StringBuilder text;
        text = new StringBuilder();

        text.append("全家使用者: ");
        text.append(super.getName());
        text.append(" / ");
        text.append("註冊狀態: ");

        if (isRegister) {
            text.append("資料填寫完整");
        } else {
            text.append("資料填寫缺漏");
        }

        return text.toString();
    }
}
  1. 建立家樂福使用者,繼承會員系統觀察者
public class Carrefour extends MemberObserver {

    public Carrefour(String name) {
        super(name);
    }

    @Override
    public String getRegister(boolean isRegister) {
        StringBuilder text;
        text = new StringBuilder();

        text.append("家樂福使用者: ");
        text.append(super.getName());
        text.append(" / ");
        text.append("註冊狀態: ");

        if (isRegister) {
            text.append("資料填寫完整");
        } else {
            text.append("資料填寫缺漏");
        }

        return text.toString();
    }
}
  1. 建立會員系統被觀察者
public abstract class MemberSubject {

    protected List<MemberObserver> memberObserverList = new ArrayList<>();

    public String add(MemberObserver memberObserver) {
        StringBuilder text;
        text = new StringBuilder();

        text.append("新增: ");
        text.append(memberObserver.getName());
        text.append(" - ");

        if (memberObserverList.add(memberObserver)) {
            text.append("新增成功");
        } else {
            text.append("新增失敗");
        }

        text.append("\n");
        return text.toString();
    }

    public String remove(MemberObserver memberObserver) {
        StringBuilder text;
        text = new StringBuilder();

        text.append("移除: ");
        text.append(memberObserver.getName());
        text.append(" - ");

        if (memberObserverList.remove(memberObserver)) {
            text.append("移除成功");
        } else {
            text.append("移除失敗");
        }

        text.append("\n");
        return text.toString();
    }

    public abstract String getRegister(boolean isRegister);
}
  1. 建立購物中心被觀察者
public class Mall extends MemberSubject {

    @Override
    public String getRegister(boolean isRegister) {
        StringBuilder text;
        text = new StringBuilder();

        text.append("\n");

        for (MemberObserver memberObserver : memberObserverList) {
            text.append(memberObserver.getRegister(isRegister));
            text.append(" / ");
            if (isRegister) {
                text.append("執行註冊");
            } else {
                text.append("不執行註冊");
            }

            text.append("\n");
        }
        text.append("\n");
        return text.toString();
    }
}

觀察者模式測試

  1. 測試案例
@Test
public void show() {
    
    StringBuilder text;
    text = new StringBuilder();
    text.append("\n");
    
    MemberObserver familyMarkAndy = new FamilyMark("Andy");
    MemberObserver familyMarkMark = new FamilyMark("Mark");
    MemberObserver carrefour = new Carrefour("AWD");
    
    MemberSubject mall = new Mall();
    
    text.append(mall.add(familyMarkAndy));
    text.append(mall.add(familyMarkMark));
    text.append(mall.add(carrefour));
    
    text.append(mall.getRegister(true));
    
    text.append(mall.remove(familyMarkAndy));
    
    text.append(mall.getRegister(false));
    
    text.append(mall.remove(familyMarkMark));
    text.append(mall.remove(carrefour));
    
    text.append(mall.getRegister(false));
    
    assertEquals("測試", text.toString());
}
  1. 執行測試
新增: Andy - 新增成功
新增: Mark - 新增成功
新增: AWD - 新增成功

全家使用者: Andy / 註冊狀態: 資料填寫完整 / 執行註冊
全家使用者: Mark / 註冊狀態: 資料填寫完整 / 執行註冊
家樂福使用者: AWD / 註冊狀態: 資料填寫完整 / 執行註冊

移除: Andy - 移除成功

全家使用者: Mark / 註冊狀態: 資料填寫缺漏 / 不執行註冊
家樂福使用者: AWD / 註冊狀態: 資料填寫缺漏 / 不執行註冊

移除: Mark - 移除成功
移除: AWD - 移除成功

上一篇
113/17 - 橋接模式(Bridge)- Kotlin
下一篇
113/19 - 觀察者模式(Observer)- Kotlin
系列文
肯定會斷賽之在 Android 開發使用設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言