用最簡單的例子說明設計模式(二)之模版方法、策略模式、組合模式、觀察者模式

模板方法模式
提供一個抽象類,將部分邏輯以具體方法或構造器的形式實現,而後聲明一些抽象方法來迫使子類實現剩餘的邏輯。不一樣的子類能夠以不一樣的方式實現這些抽象方法(多態實現),從而實現不一樣的業務邏輯。
 
使用場景
1)多個子類有公有的方法,而且邏輯基本相同時
2)重要、複雜的算法,能夠把核心算法設計爲模板方法
3)重構時,模板方法模式是一個常常使用的模式
public abstract class AbstractWork {
     
    protected void getUp() {
        System.out.println("起牀啦!");
    }
 
    protected abstract void goToWork();
 
    protected abstract void work();
 
    protected abstract void getOffWork();
 
    /*
     * TemplateMethod,你們都擁有共同的執行步驟
     */
    public final void newDay() {
        getUp();
        goToWork();
        work();
        getOffWork();
    }
 
}

public class BossWork extends AbstractWork {
     
    @Override
    protected void goToWork() {
        System.out.println("老闆開車去上班");
    }
 
    @Override
    protected void work() {
        System.out.println("老闆的分配工做給員工");
    }
 
    @Override
    protected void getOffWork() {
        System.out.println("老闆開車去下班");
    }
 
}

public class StaffWork extends AbstractWork {
     
    @Override
    protected void goToWork() {
        System.out.println("員工作公交去上班");
 
    }
 
    @Override
    protected void work() {
        System.out.println("員工處理具體工做");
    }
 
    @Override
    protected void getOffWork() {
        System.out.println("員工作公交下班");
    }
 
}

public class Test {
    public static void main(String[] args) {
        BossWork bossWork = new BossWork();
        StaffWork staffWork = new StaffWork();
        bossWork.newDay();
        System.out.println("------------------------");
        staffWork.newDay();
    }
}

  

 
 
策略模式
定義了算法家庭,分別封裝起來。讓它們之間能夠互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。
 一個類定義了多種行爲,而且這些行爲在這個類的方法中以多個條件語句的形式出現,那麼可使用策略模式避免在類中使用大量的條件語句。
 
 
public interface AbstractStrategy {
    //按距離來計算價格
    int calculatePrice(int km);
}

public class BusStrategy implements AbstractStrategy {
    @Override
    public int calculatePrice(int km) {
        int extraTotal = km - 10;
        int extraFactor = extraTotal / 5;
        int fraction = extraTotal % 5;
        int price = 1 + extraTotal % 5;
        return fraction > 0 ? ++price : price;
    }
}

public class TaxiStrategy implements AbstractStrategy {
    @Override
    public int calculatePrice(int km) {
        return km * 2;
    }
}

public class Context {

    private AbstractStrategy strategy;

    public void setStrategy(AbstractStrategy strategy) {
        this.strategy = strategy;
    }

    public int calclatePrice(int km) {
        return strategy.calculatePrice(km);
    }

    public static void main(String[] strings) {
        Context calculator = new Context();
        calculator.setStrategy(new BusStrategy());
//        calculator.setStrategy(new TaxiStrategy());
        System.out.println("公交車20km價格:" + calculator.calclatePrice(20));
    }

}

傳統寫法android

    //PriceCalculator 類很明顯的問題就是並非單一職責,首先它承擔計算公交車和地鐵乘坐價格的職責,
    //另外一個問題就是經過if-else的形式來判斷使用哪一種計算形式。當咱們增長一種出行方式時,如出租車,
    //那麼咱們就須要在PriceCalculator 中增長一個方法來計算出租車出行的價格,而且在calculatePrice(int km, int type)函數增長一個判斷
    public static class PriceCalculator {
        private static final int TAXI = 3;
        private static final int BUS = 1;
        private static final int SUBWAY = 2;

        public static void main(String[] strings) {
            PriceCalculator calculator = new PriceCalculator();
            System.out.println("作20km公交票價:" + calculator.calculatePrice(20, BUS));
            System.out.println("作20km地鐵票價:" + calculator.calculatePrice(20, SUBWAY));
        }


        private int busPrice(int km) {
            return km * 1;
        }


        public int taxiPrice(int km) {
            return km * 7;
        }

        /**
         * 根據不一樣類型計算
         */
        int calculatePrice(int km, int type) {
            if (type == BUS) {
                return busPrice(km);
            } else if (type == SUBWAY) {
                return taxiPrice(km);
            }
            return 0;
        }
    }

  

 

組合模式
使用戶對單個對象和組合對象的使用具備一致性。將對象組合成樹形結構以表示「部分-總體」的層次結構。
Component : 組合中的對象聲明接口,在適當的狀況下,實現全部類共有接口的默認行爲。
Leaf : 表示葉節點對象。葉子節點沒有子節點。
Composite : 定義枝節點行爲,用來存儲子部件,在 Component 接口中實現與子部件相關的操做。例如 Add 和 Remove
 
public abstract class File {

    private String name;

    public File(String name) {
        this.name = name;
    }

    //操做方法
    public String getName() {
        return name;
    }

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

    public abstract void watch();

    //組合方法
    public void add(File file) {
        throw new UnsupportedOperationException();
    }

    public void remove(File file) {
        throw new UnsupportedOperationException();
    }

    public File getChild(int position) {
        throw new UnsupportedOperationException();
    }
}

public class Folder extends File {

    private List<File> mFileList;

    public Folder(String name) {
        super(name);
        mFileList = new ArrayList<>();
    }

    @Override
    public void watch() {
        StringBuffer fileName = new StringBuffer();
        for (File file : mFileList) {
            fileName.append(file.getName() + ";");
        }
       
          System.out.println("組合模式:這是一個叫" + getName() + "文件夾,包含" + mFileList.size() + "個文件,分別是:" + fileName);

    }

    @Override
    public void add(File file) {
        mFileList.add(file);
    }

    @Override
    public void remove(File file) {
        mFileList.remove(file);
    }

    @Override
    public File getChild(int position) {
        return mFileList.get(position);
    }
}

public class TextFile extends File {

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

    @Override
    public void watch() {
        System.out.println("組合模式:這是一個叫" + getName() + "文本文件");
    }
}

public class testComposite {
    public static void main(String[] strings) {
        TextFile textFileA = new TextFile("a.txt");
        TextFile textFileB = new TextFile("b.txt");
        TextFile textFileC = new TextFile("c.txt");

        textFileA.watch();
    //  textFileA.add(textFileB);//調用會拋咱們在抽象接口中寫的異常

        Folder folder = new Folder("學習資料");
        folder.add(textFileA);
        folder.add(textFileB);
        folder.add(textFileC);
        folder.watch();
        folder.getChild(1).watch();
        
        Folder folder1 = new Folder("我的資料");
        folder1.add(textFileA);
        folder1.add(textFileB);
        //能夠隨便組合
        Folder folder2 = new Folder("D盤資料");
        folder2.add(folder);
        folder2.add(folder1);
      
    }

}

  

 
 
觀察者模式
定義對象之間的一種一對多依賴關係,使得每當一個對象狀態發生改變時,其相關依賴對象皆可獲得通知並被自動更新。
觀察者模式在android中的實際運用:回調模式
回調模式:實現了抽象類/接口的實例實現了父類的提供的抽象方法 後,將該方法交還給父類來處理。
例如: 經過 setOnClickListener() 方法,Button 持有 OnClickListener 的引用(這一過程沒有在圖上畫出);當用戶點擊時,Button 自動調用 OnClickListener 的 onClick() 方法。另外,若是把這張圖中的概念抽象出來(Button(view) -> 被觀察者、OnClickListener -> 觀察者、setOnClickListener() -> 訂閱,onClick() -> 事件),就由專用的觀察者模式(例如只用於監聽控件點擊)轉變成了通用的觀察者模式。
 
public class ObserverPattern {

    public interface Observer {
        void update(String state);
    }

    public class ConcreteObserver implements Observer {
        // 觀察者狀態
        private String observerState;

        @Override
        public void update(String state) {
            // 更新觀察者狀態,讓它與目標狀態一致
            observerState = state;
            System.out.println("ConcreteObserver State :" + observerState);
        }
    }

    /**
     * 抽象訂閱者(目標者)
     * 被觀察者
     *
     */
    public abstract class Subject {

        // 保存註冊的觀察者對象
        private List<Observer> mObservers = new ArrayList<>();

        //註冊觀察者對象
        public void attach(Observer observer) {
            mObservers.add(observer);
            System.out.println("Attached an observer");
        }

        //註銷觀察者對象
        public void detach(Observer observer) {
            mObservers.remove(observer);
        }

        // 通知全部註冊的觀察者對象
        public void nodifyObservers(String newState) {
            for (Observer observer : mObservers) {
                observer.update(newState);
            }
        }
    }

    public class ConcreteSubject extends Subject {

        private String state;

        public String getState() {
            return state;
        }

        public void change(String newState) {
            state = newState;
            System.out.println("ConcreteSubject State:" + state);
            //狀態發生改變,通知觀察者
            nodifyObservers(state);
        }
    }

    public static void main(String[] args) {
        ObserverPattern observerPattern = new ObserverPattern();
        ConcreteSubject concreteSubject = observerPattern.new ConcreteSubject();
        Observer observer1 = observerPattern.new ConcreteObserver();
        Observer observer2 = observerPattern.new ConcreteObserver();
        // 將觀察者對象註冊到目標對象上
        concreteSubject.attach(observer1);
        concreteSubject.attach(observer2);
        // 改變目標對象的狀態
        concreteSubject.change("I change");
    }
}

  

 

相關源碼:git

https://github.com/peiniwan/DesignPattern.git
相關文章
相關標籤/搜索