Decorator Pattern有符合SOLID原則嗎?

2023-05-22

前言

在物件導向的世界裡,我們常常掛在嘴邊的五大原則每天聽每天看。網路上也有很多人分享SOLID怎麼寫、怎麼設計。 這篇將會先以程式碼展示,可能符合SOLID的設計與開發流程,我們一起來看看吧。

我將以幾段程式碼呈現我認為有符合SOLID原則的設計(以 Dart 語言為例)

定義介面

假設我們要從資料庫取得用戶資訊我們可以定義一個介面

abstract class Users {
    List<User> values(); // Returns the result.
}

實作

假設資料庫在遠端我們可以依據 Users 實作

class ApiUsers extends Users {
  @override
  List<User> values() {
    // The fetching api here.
  }
}

同理,假設資料在本地的話呢?

class LocalUsers extends Users {
  @override
  List<User> values() {
    // The gathering local data here.
  }
}

使用時會是長這個樣子

  Users users = ApiUsers(); // or LocalUsers
  users.values();

目前為止,一件事情就新增一個類別,似乎有點囉唆了?讓我們看下去...


新需求!

接著,隨著時間推移,需求也跟著增加/修改了 假如根據需求,我需要將這個拿出來的 User 物件作過濾,我們可以新增 FilteredUsers 類別

class FilteredUsers extends Users {
  final Users original; // Depend on User abstract object. (Decorator)

  FilteredUsers(this.original);

  @override
  List<User> values() {
    // gather the original values and do the filter.
    return original.values().where((element) => true).toList();
  }
}

現在的使用的部分呢?

  Users getUsers = FilteredUsers(ApiGetUsers()); // Add FilteredUsers
  getUsers.values();

其實挺直覺,對嗎? 增加功能時,我們除了為了新功能新增類別外,也只是增加引用端的建構子呼叫而已。

這樣有符合SOLID嗎?

接下來呢?以下需求留給讀者們想想能不能用此方式實作