# Decorator Pattern 有符合SOLID嗎? #### 前言 在物件導向的世界裡,我們常常掛在嘴邊的五大原則每天聽每天看。網路上也有很多人分享SOLID怎麼寫、怎麼設計。 這篇將會先以程式碼展示,可能符合SOLID的設計與開發流程,我們一起來看看吧。 我將以幾段程式碼呈現我認為有符合SOLID原則的設計(以 `Dart` 語言為例) #### 定義介面 假設我們要從資料庫取得用戶資訊我們可以定義一個介面 ```dart abstract class Users { List<User> values(); // Returns the result. } ``` #### 實作 假設資料庫在遠端我們可以依據 `Users` 實作 ```dart class ApiUsers extends Users { @override List<User> values() { // The fetching api here. } } ``` 同理,假設資料在本地的話呢? ```dart class LocalUsers extends Users { @override List<User> values() { // The gathering local data here. } } ``` 使用時會是長這個樣子 ```dart Users users = ApiUsers(); // or LocalUsers users.values(); ``` 目前為止,一件事情就新增一個類別,似乎有點囉唆了?讓我們看下去... ---- #### 新需求! 接著,隨著時間推移,需求也跟著增加/修改了 假如根據需求,我需要將這個拿出來的 `User` 物件作過濾,我們可以新增 `FilteredUsers` 類別 ```dart 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(); } } ``` 現在的使用的部分呢? ```dart Users getUsers = FilteredUsers(ApiGetUsers()); // Add FilteredUsers getUsers.values(); ``` 其實挺直覺,對嗎? 增加功能時,我們除了為了新功能新增類別外,也只是增加引用端的建構子呼叫而已。 #### 這樣有符合SOLID嗎? - 單一職責 => 每個類別都如同命名,只做一件事 - 開放封閉原則 => 新增功能時,寫好的類別不用改。 - 里氏替換原則 => 所有的類別都是依賴 `User` 介面,如 `FilteredUsers` 內的 original 變數是可以替換的。 - 介面隔離 => 因為每個類別都是實作 `User` 介面,有規範公開的接口為 `values` 方法 - 依賴反向 => 引用端依賴 `User`介面,而非依賴實作類別。 (除了建構式以外) 接下來呢?以下需求留給讀者們想想能不能用此方式實作 - 整合Api與本地的 `User` 來源 - 快取 後記: 同步發佈至我的個人[Blog](https://larryhsiao.com/is-decroator-pattern-solid/)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up