kyle shanks
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    --- title: 'Stragety 策略 模式' disqus: kyleAlien --- Stragety 策略 模式 === ## Overview of Content 如有引用參考請詳註出處,感謝 :smile: > 定義一系列的演算法,並將每個一個**演算法封裝**,並 ==可**互相取代**== :::success * 如果喜歡讀更好看一點的網頁版本,可以到我新做的網站 [**DevTech Ascendancy Hub**](https://devtechascendancy.com/) 本篇文章對應的是 [**Stragety 策略模式 | 解說實現 | Android Framework 動畫**](https://devtechascendancy.com/object-oriented_design_stragety_framework/) ::: [TOC] ## Stragety 使用場景 1. 對同一類型的問題有多種處理方式,多個 `if/else`,`switch/case` 判斷時 2. 需要**安全封裝多種`同一類型`的操作** ### Stragety 定義 & UML * **Stragety 定義**: 定義一組算法,並將其封裝起來,之後可以快速互換 * **Stragety UML**: 透過將共同方法定義在抽象,透過注入細節,實現相同方法 but 不同結果 | 角色 | 功能 | | -------- | -------- | | `Context` | 上下文角色,封裝 `IStragety`,屏蔽高層模塊對策略的直接訪問 | | `IStragety` | 共同方法的抽象接口 | | `ConstractStragetyA、B` | 實作類演算法類(細節實現) | > ![](https://hackmd.io/_uploads/HkeJoFoSn.png) ### Stragety 設計 - 優缺點 * **Stragety 設計優點** * 結構清晰,簡單直觀,擴充方便 * 透過注入相對而言耦合度較低 * 不同演算法出現問題時,可以**分開維護**,也符合開閉原則 * **Stragety 設計缺點** * 隨著演算法的增加,實現子類會變多 * 另一個代價是,外部需要知道使用的策略!不符合迪米特原則(最少知識原則) ## Stragety 實現 :::info 假設去韓國旅行有三種方式,自助旅行、半自助旅行、旅行社,每種選擇方式所花費的金額也不一樣 ::: 最簡單直覺的寫法是使用 `if / else`、`switch / case` 去分類,但 **這種寫法不符合開閉原則**,每次新增一個旅遊金額算法,都需要修改 TravelCal 方法 ```java= public class TravelCal { public int getTravelCal(String type) { int result; if("Agency".equals(type)) { result = 300; } else if("SelfHelp".equals(type)) { result = 50; } else if("Backpacking".equals(type)) { result = 100; } else { result = -1; } return result; } } ``` ### Stragety 實現標準 1. **`IStragety` 介面**:宣告共同的抽象方法,以目前案例就是定義每一種旅行方式所需的花費 ```java= // IStragety.java public interface TravelCast { // 共同抽象 int calCast(); } ``` 2. **`ConstractStragety` 類**:定義細節,讓每一個方案去實作計算花費金額 ```java= // 旅行社 public class Agency implements TravelCast { @Override public int calCast() { return 300; } } // 自助 public class SelfHelp implements TravelCast { @Override public int calCast() { return 100; } } // 背包客 public class Backpacking implements TravelCast { @Override public int calCast() { return 50; } } ``` * User 使用:透過替換實作細節,來達到不同的金額 :::success * 開閉原則: 如果有新的旅行方案,同樣透過繼承 `TravelCast` 抽象來拓展,並不會觸碰到其他類 ::: ```java= public class TestStrategy { public static void main(String[] args) { TravelCast travelCast; travelCast = new Agency(); printCast(travelCast); travelCast = new SelfHelp(); printCast(travelCast); travelCast = new Backpacking(); printCast(travelCast); } public static void printCast(TravelCast travelCast) { System.out.println(travelCast.getClass().getSimpleName() + " Cast: " + travelCast.calCast()); } } ``` **--實作--** > ![](https://i.imgur.com/0Ymbbpm.png) ### 管理 Stragety 實作 - Context * 在最原始的 Stragety 實作,User 類會了解到細節 (TravelCast 的實作),這就不符合 `最少知識`、`依賴導致` 設計原則 * 這邊我們透過一個 `Manager 管理類`,透過外部注入 Option 選項,來決定最終要產生的花費 > 上面重複,沒有修改的類 (IStragety、ConstractStragety),這邊不會列出 > ![](https://hackmd.io/_uploads/ryBvatjBn.png) 1. **Manager**:新增一個管理類,聚合管理所有的 IStragety,並給予預設值 ```java= // Manager 類 public class TravelManager { enum Option { BACK_PACKING, SELF_HELP, AGENCY } // 聚合所有 TravelCast 抽象 private final Map<Option, TravelCast> map = new HashMap<>() { { put(Option.BACK_PACKING, new Backpacking()); put(Option.SELF_HELP, new SelfHelp()); put(Option.AGENCY, new Agency()); } }; private Option option; public TravelManager() { // 設定 default option = Option.AGENCY; } // 透過注入,來達到切換細節 public TravelManager setOption(Option option) { this.option = option; return this; } public void printCast() { TravelCast travelCast = map.get(option); if(travelCast == null) { throw new IllegalAccessError("setTravelCast first"); } System.out.println(travelCast.getClass().getSimpleName() + " Cast: " + travelCast.calCast()); } } ``` :::success * 這裡有另外一種方式叫做 **策略枚舉**,透過枚舉的封裝,可以加強可讀性 ::: 2. **User 使用**:**透過 Manager 來 ++管理細節++**,而 User 只需要知道 Manager 即可 ```java= // User 使用 public class TestStrategy { public static void main(String[] args) { TravelManager travelManager = new TravelManager(); travelManager.setOption(TravelManager.Option.AGENCY).printCast(); travelManager.setOption(TravelManager.Option.SELF_HELP).printCast(); travelManager.setOption(TravelManager.Option.BACK_PACKING).printCast(); } } ``` :::warning * **Manager(Context) 不符合開閉原則**: 雖然這裡透過 Manager 來管理 IStragety 所有細節,但如果有新增類,就需要手動修改 Manager 類 ::: :::success * 這裡還可以使用工廠、代理、享元... 等等模式來實做 Manager(依需求決定) ::: ## Android source 動畫 動畫透過人類的 **視覺暫留** 來達成,透過快速切換來達到動畫的效果 > 視覺暫留: 對於上個映像會暫時留在眼中 | 來源 | 每秒楨數 | | -------- | -------- | | 標準電影 | 24 楨/秒 | | Android 動畫 | 60 楨/秒 | ### 動畫 - [TimeInterpolator](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/animation/TimeInterpolator.java) 插值器 * 透過 `TimeInterpolator` 插值器,可以讓我們接收動畫的運作時間,透過時間的百分比來調整動畫的速度 * 下圖代表給予相同的時間,但不同插值器會返回不同結果,從這裡其實就可以看出 **Stragety 設計,不同的插值器代表了不同的算法** > ![](https://i.imgur.com/JHYACsq.png) * 常見 `Interpolator` 插值器如下 | 插值器 | 對動畫的功能 | | -------- | -------- | | [**LinearInterpolator**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/LinearInterpolator.java) | 線性加速 | | [**AccelerateDecelerateInterpolator**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/AccelerateDecelerateInterpolator.java) | 加速 & 減速 | | [**DecelerateInterpolator**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/DecelerateInterpolator.java) | 減速 | > ![](https://i.imgur.com/IXfzNa0.png) ### 動畫 - [TypeEvaluator](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/animation/TypeEvaluator.java) 類型估值器 * TypeEvaluator 的功能是,得到 TimeInterpolator 插值器的數值後,將得到的時間百分比、屬性起始值、目標值來運算最終結果,**將最終運算結果交給 View** ```java= // TypeEvaluator.java public interface TypeEvaluator<T> { // 泛型 public T evaluate(float fraction, T startValue, T endValue); } ``` * 常見的 `Evaluator` 類型估值器如下 | 插值器 | 對動畫的功能 | | -------- | -------- | | FloatEvaluator | 浮點數運算 | | IntEvaluator | 整數運算 | | ArgbEvaluator | 顏色運算 | ```java= // IntEvaluator.java public class IntEvaluator implements TypeEvaluator<Integer> { /** * fraction 是時間插值器運算出的值 (0 ~ 1 之間) */ public Integer evaluate(float fraction, Integer startValue, Integer endValue) { int startInt = startValue; return (int)(startInt + fraction * (endValue - startInt)); } } ``` > ![](https://i.imgur.com/yn4CBrl.png) ### Animation 基礎使用 1. 設定動畫 xml 檔案 ```xml= <!-- R.anim.click_btn --> <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300"> <scale android:fromXScale="0.5" android:fromYScale="0.5" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.0" android:toYScale="1.0"/> </set> ``` 2. 使用 `AnimationUtils` 來讀取 xml 檔案 ```java= // 讀取 xml 資源檔 Animation animation = AnimationUtils.loadAnimation(this, R.anim.click_btn); ``` 3. 將 Animation 設定給 View ```java= Button btn = findViewById(R.id.btn); // Button 加載動畫 btn.startAnimation(animation); ``` :::info * startAnimation 是 View 的方法 ::: ### [View](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java) - startAnimation 啟動動畫 ```java= // View.java public void startAnimation(Animation animation) { // 初始化動畫開始時間 animation.setStartTime(Animation.START_ON_FIRST_FRAME); // 對該 View 設定 Animation setAnimation(animation); // 刷新 Parent 緩存 invalidateParentCaches(); // 刷新 View 自身 invalidate(true); } // ------------------------------------------------------- // Animation.java public static final int START_ON_FIRST_FRAME = -1; ``` * 刷新後 ViewGroup 會透過 `dispatchDraw` 方法,對 View 的部分區域重繪,ViewGroup 重繪時會呼叫 ViewGroup#**drawChild** 方法 ```java= // ViewGroup.java protected boolean drawChild(Canvas canvas, View child, long drawingTime) { // @ 追蹤 draw 方法 return child.draw(canvas, this, drawingTime); } // ------------------------------------------------------------- // View.java boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { ... 省略部分 if (a != null) { // @ 追蹤 applyLegacyAnimation 方法 more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); ... } else { ... 省略部分 } } ``` 1. applyLegacyAnimation 方法:初始化、標記 View 動畫啟動 ```java= // View.java @CallSuper protected void onAnimationStart() { // 標記該 View 已啟動 Animation mPrivateFlags |= PFLAG_ANIMATION_STARTED; } private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired) { Transformation invalidationTransform; final int flags = parent.mGroupFlags; final boolean initialized = a.isInitialized(); // 檢查是否初始化 if (!initialized) { // 尚未初始化則初始化 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); // 標記 View 啟動動畫 onAnimationStart(); } // 儲存動畫訊息 final Transformation t = parent.getChildTransformation(); // @ 追蹤 getTransformation 方法 // 獲取動畫相關值 boolean more = a.getTransformation(drawingTime, t, 1f); ... if (more) { if (!a.willChangeBounds()) { ... 省略部分 } else { if (parent.mInvalidateRegion == null) { parent.mInvalidateRegion = new RectF(); } final RectF region = parent.mInvalidateRegion; // 獲取重繪區域 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region, invalidationTransform); // child 繪製的動畫可能螢幕之外,需要確保該刷新不會被取消 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION; // 計算有效區域 final int left = mLeft + (int) region.left; final int top = mTop + (int) region.top; // ViewGroup 刷新指定區塊 parent.invalidate(left, top, left + (int) (region.width() + .5f), top + (int) (region.height() + .5f)); } } return more; } ``` 2. Animation#**getTransformation** 方法:**重點是計算動畫時間**,決定該動畫是否仍需要繪製,返回 true 代表要繪製動畫,如果 ```java= // Animation.java Interpolator mInterpolator; public boolean getTransformation(long currentTime, Transformation outTransformation, float scale) { mScaleFactor = scale; // @ 追蹤 getTransformation 方法 return getTransformation(currentTime, outTransformation); } public boolean getTransformation(long currentTime, Transformation outTransformation) { if (mStartTime == -1) { // 設定動畫啟動時間 mStartTime = currentTime; } // 該 Animation 總時間 final long startOffset = getStartOffset(); final long duration = mDuration; // 時間流逝的百分比 float normalizedTime; if (duration != 0) { normalizedTime = ((float) (currentTime - (mStartTime + startOffset))) / (float) duration; } else { // 動畫尚未啟動 (延遲) normalizedTime = currentTime < mStartTime ? 0.0f : 1.0f; } // 動畫完成 or 取消,expired = true // 1.0 代表動畫時間已經過 final boolean expired = normalizedTime >= 1.0f || isCanceled(); mMore = !expired; ... // 動畫時間正在運作中 if ((normalizedTime >= 0.0f || mFillBefore) && (normalizedTime <= 1.0f || mFillAfter)) { ... 省略部分 // 插值器 final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime); // @ 分析 applyTransformation 方法 applyTransformation(interpolatedTime, outTransformation); } ... if (!mMore && mOneMoreTime) { mOneMoreTime = false; return true; } return mMore; } ``` * 從這裡可以看到 [**Interpolator**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/Interpolator.java) 的身影,同時也可以發現 **使用者如果設定 ++不同 Interpolator 也會也不同的效果++** ```java= // Animation.java public Animation() { // 設定預設插值器 ensureInterpolator(); } public void setInterpolator(Interpolator i) { mInterpolator = i; } protected void ensureInterpolator() { if (mInterpolator == null) { // 預設插值器為 AccelerateDecelerateInterpolator mInterpolator = new AccelerateDecelerateInterpolator(); } } ``` > ![](https://i.imgur.com/4fcG8Sw.png) * 預設插值器為 [**AccelerateDecelerateInterpolator**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/AccelerateDecelerateInterpolator.java):這是加減速插值器 ```java= // AccelerateDecelerateInterpolator.java @HasNativeInterpolator public class AccelerateDecelerateInterpolator extends BaseInterpolator implements NativeInterpolator { public AccelerateDecelerateInterpolator() { } @SuppressWarnings({"UnusedDeclaration"}) public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) { } public float getInterpolation(float input) { // 加速插值器 return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f; } /** @hide */ @Override public long createNativeInterpolator() { // 減速插值器 return NativeInterpolatorFactory.createAccelerateDecelerateInterpolator(); } } ``` ### 里式原則應用 - applyTransformation * [**Animation**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/Animation.java)#applyTransformation 是一個空實現,給每一個繼承於它的子類實現細節,這就是理式原則的典型應用,父類可以任意地被子類替換 ```java= // Animation.java protected void applyTransformation(float interpolatedTime, Transformation t) { } ``` * 如過動畫 xml 有設定 alpha 值,則會對應到 [**AlphaAnimation 類**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/AlphaAnimation.java)、選轉則是對應到 [**RotateAnimation 類**](https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/animation/RotateAnimation.java) ```java= // AlphaAnimation.java public class AlphaAnimation extends Animation { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { final float alpha = mFromAlpha; // 設定透明度 t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime)); } } // ----------------------------------------------------- // RotateAnimation.java public class RotateAnimation extends Animation { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime); float scale = getScaleFactor(); if (mPivotX == 0.0f && mPivotY == 0.0f) { t.getMatrix().setRotate(degrees); } else { t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale); } } } ``` ## 更多的物件導向設計 物件導向的設計基礎如下,如果是初學者或是不熟悉的各位,建議可以從這些基礎開始認識,打好基底才能走個更穩(在學習的時候也需要不斷回頭看)! :::info * [**設計建模 2 大概念- UML 分類、使用**](https://devtechascendancy.com/introduction-to-uml-and-diagrams/) * [**物件導向設計原則 – 6 大原則(一)**](https://devtechascendancy.com/object-oriented-design-principles_1/) * [**物件導向設計原則 – 6 大原則(二)**](https://devtechascendancy.com/object-oriented-design-principles_2/) ::: ### 創建模式 - Creation Patterns * [**創建模式 PK**](https://devtechascendancy.com/pk-design-patterns-factory-builder-best/) * **創建模式 - `Creation Patterns`**: 創建模式用於「**物件的創建**」,它關注於如何更靈活、更有效地創建對象。這些模式可以隱藏創建對象的細節,並提供創建對象的機制,例如單例模式、工廠模式… 等等,詳細解說請點擊以下連結 :::success * [**Singleton 單例模式 | 解說實現 | Android Framework Context Service**](https://devtechascendancy.com/object-oriented_design_singleton/) * [**Abstract Factory 設計模式 | 實現解說 | Android MediaPlayer**](https://devtechascendancy.com/object-oriented_design_abstract-factory/) * [**Factory 工廠方法模式 | 解說實現 | Java 集合設計**](https://devtechascendancy.com/object-oriented_design_factory_framework/) * [**Builder 建構者模式 | 實現與解說 | Android Framwrok Dialog 視窗**](https://devtechascendancy.com/object-oriented_design_builder_dialog/) * [**Clone 原型模式 | 解說實現 | Android Framework Intent**](https://devtechascendancy.com/object-oriented_design_clone_framework/) * [**Object Pool 設計模式 | 實現與解說 | 利用 JVM**](https://devtechascendancy.com/object-oriented_design_object-pool/) * [**Flyweight 享元模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_flyweight/) ::: ### 行為模式 - Behavioral Patterns * [**行為模式 PK**](https://devtechascendancy.com/pk-design-patterns-cmd-strat-state-obs-chain/) * **行為模式 - `Behavioral Patterns`**: 行為模式關注物件之間的「**通信**」和「**職責分配**」。它們描述了一系列對象如何協作,以完成特定任務。這些模式專注於改進物件之間的通信,從而提高系統的靈活性。例如,策略模式、觀察者模式… 等等,詳細解說請點擊以下連結 :::warning * [**Stragety 策略模式 | 解說實現 | Android Framework 動畫**](https://devtechascendancy.com/object-oriented_design_stragety_framework/) * [**Interpreter 解譯器模式 | 解說實現 | Android Framework PackageManagerService**](https://devtechascendancy.com/object-oriented_design_interpreter_framework/) * [**Chain 責任鏈模式 | 解說實現 | Android Framework View 事件傳遞**](https://devtechascendancy.com/object-oriented_design_chain_framework/) * [**State 狀態模式 | 實現解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_state/) * [**Specification 規格模式 | 解說實現 | Query 語句實做**](https://devtechascendancy.com/object-oriented_design_specification-query/) * [**Command 命令、Servant 雇工模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_command_servant/) * [**Memo 備忘錄模式 | 實現與解說 | Android Framwrok Activity 保存**](https://devtechascendancy.com/object-oriented_design_memo_framework/) * [**Visitor 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_visitor_dispatch/) * [**Template 設計模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_template/) * [**Mediator 模式設計 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_mediator/) * [**Composite 組合模式 | 實現與解說 | 物件導向設計**](https://devtechascendancy.com/object-oriented_programming_composite/) ::: ### 結構模式 - Structural Patterns * [**結構模式 PK**](https://devtechascendancy.com/pk-design-patterns-proxy-decorate-adapter/) * **結構模式 - `Structural Patterns`**: 結構模式專注於「物件之間的組成」,以形成更大的結構。這些模式可以幫助你確保當系統進行擴展或修改時,不會破壞其整體結構。例如,外觀模式、代理模式… 等等,詳細解說請點擊以下連結 :::danger * [**Bridge 橋接模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_bridge/) * [**Decorate 裝飾模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_decorate/) * [**Proxy 代理模式 | 解說實現 | 分析動態代理**](https://devtechascendancy.com/object-oriented_design_proxy_dynamic-proxy/) * [**Iterator 迭代設計 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_iterator/) * [**Facade 外觀、門面模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_facade/) * [**Adapter 設計模式 | 解說實現 | 物件導向設計**](https://devtechascendancy.com/object-oriented_design_adapter/) ::: ## Appendix & FAQ :::info ::: ###### tags: `Java 設計模式` `基礎進階`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    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

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully