1. 程式人生 > >[19/05/02-星期四] GOF23_行為型模式(狀態模式、觀察者模式、備忘錄模式)

[19/05/02-星期四] GOF23_行為型模式(狀態模式、觀察者模式、備忘錄模式)

car 參數 home arr 進行 hand dsta sta rec

一、狀態模式

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

【狀態接口】

/***
 * 房間"狀態"接口
 */
package cn.sxt.state;

public interface State {
    void  handle();

}

【管理狀態類】

/***
 * 環境、上下文類, 管理房間的狀態
 *如果這是銀行系統,這個類就是賬號,根據狀態的不同,進行不同的操作
 */
package cn.sxt.state;

public class HomeContext {
    private State state;


    public
void setState(State state) { System.out.println("修改房間的狀態!"); this.state = state; state.handle(); } }

【房間狀態】

/***
 * "空閑"狀態
 */
package cn.sxt.state;

public class FreeState implements State{

    @Override
    public void handle() {
        System.out.println(
"房間空閑,沒人入住!"); } } /*** * "有人住、房間有人"類 */ package cn.sxt.state; public class CheckedInState implements State{ @Override public void handle() { System.out.println("房間有人,請勿打擾!"); } } /*** * "已預訂" 類 */ package cn.sxt.state; public class
BookedState implements State{ @Override public void handle() { System.out.println("房間有人預定!"); } }

【客戶類】

/**
 * 客戶
 */
package cn.sxt.state;

public class Client {
    public static void main(String[] args) {
        HomeContext ctx=new HomeContext();//狀態對象
        ctx.setState(new FreeState());//設置狀態為 空閑狀態
        ctx.setState(new BookedState());
    }

}

二、觀察者模式(Observer)

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

【目標類-廣播站】

/**
 * "目標"類 廣播站
 */
package cn.sxt.observer;

import java.util.ArrayList;
import java.util.List;

public class Subject  {
    protected List<Observer> list=new ArrayList<Observer>();
    
    public void registerObserver(Observer obs){
        list.add(obs);//註冊觀察者,就是聽眾
    }
    
    public void removeObserver(Observer obs){
        list.remove(obs);//刪除觀察者,就是聽眾
    }
    
    public void notifyAllObserver() {//通知所有觀察者,更新狀態
        for (Observer obs : list) {
            obs.update(this);
        }
    }

}


/***
 * "一個具體的廣播站"
 */
package cn.sxt.observer;

public class ConcreteSubject extends Subject {
    private String state;

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
        this.notifyAllObserver();//狀態變化有變化請通知其它的觀察者
    }
    

}

【觀察者-聽眾】

/***
 * "觀察者"接口
 */
package cn.sxt.observer;

public interface Observer {
    void update(Subject subject);

}

/***
 * A觀察者
 */
package cn.sxt.observer;

public class ObserverA implements Observer{
    private String myState;//自己的狀態跟目標對象保持一致

    @Override
    public void update(Subject subject) {
        myState=( (ConcreteSubject)subject ).getState();    
    }

    public String getMyState() {
        System.out.print("系統消息:");
        return myState;
    }

    public void setMyState(String myState) {
        this.myState = myState;
    }
    
    
}

【客戶端】

/**
 * 
 */
package cn.sxt.observer;

public class Client {
    public static void main(String[] args) {
        //目標對象,廣播站
        ConcreteSubject subject=new ConcreteSubject();
        //3個觀察者 聽眾
        ObserverA obs1=new ObserverA();
        ObserverA obs2=new ObserverA();
        ObserverA obs3=new ObserverA();
        
        //讓這3個觀察者添加到觀察者容器中
        subject.registerObserver(obs1);
        subject.registerObserver(obs2);
        subject.registerObserver(obs3);
        
        //改變狀態 開始廣播
        subject.setState("明天上午8:00開會");
        
        //看看觀察者的狀態
        System.out.println(obs1.getMyState());
        System.out.println(obs2.getMyState());
        System.out.println(obs3.getMyState());
    }
}

使用系統提供的觀察類

【具體的廣播站】

/***
 * 一個具體的廣播站 ,使用Java提供的 目標類java.util.Observable
 */
package cn.sxt.observer2;

import java.util.Observable;

public class ConcreteSubject extends Observable {
    private String state;
    
    public void setState(String state) {
        this.state = state;
        setChanged();//調用jar的方法,表示目標對象已經做了更改
        notifyObservers(state);//通知所有的觀察者,jar包的方法
    }
    
    public String getState() {
        return state;
    }
    

}

【具體的聽眾】

/**
 * 
 */
package cn.sxt.observer2;

import java.util.Observable;
import java.util.Observer;


public class ObserverA implements Observer{//使用jar中的接口
    
    private String myState;
    
    @Override
    public void update(Observable o, Object arg) {//2個參數:主題對象
        myState=( (ConcreteSubject) o).getState();    
    }
    
    public String getMyState() {
        System.out.print("系統消息:");
        return myState;
    }

    public void setMyState(String myState) {
        this.myState = myState;
    }

}

【客戶端測試】

/**
 * 
 */
package cn.sxt.observer2;

public class Client {
    public static void main(String[] args) {
        //目標對象,廣播站
        ConcreteSubject subject=new ConcreteSubject();
        //3個觀察者 聽眾
        ObserverA obs1=new ObserverA();
        ObserverA obs2=new ObserverA();
        ObserverA obs3=new ObserverA();
        
        //添加觀察者    
        subject.addObserver(obs1);
        subject.addObserver(obs2);
        subject.addObserver(obs3);
        
        //改變狀態 開始廣播
        subject.setState("明天上午9:00開會");
        
        //看看觀察者的狀態
        System.out.println(obs1.getMyState());
        System.out.println(obs2.getMyState());
        System.out.println(obs3.getMyState());
    }
}

三、備忘錄模式(memento)

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

【源發類】

/***
 *源發器類 保存雇員的信息 
 */
package cn.sxt.memento;

public class Emp {
    private String name;
    private int age;
    private double salary;
    
    //進行備忘操作
    public EmpMemento memento() {
        return new EmpMemento(this);//表示當前對象的信息
    }
    //進行數據恢復,恢復備忘錄的值
    public void recovery(EmpMemento mmt) {
        this.name=mmt.getName();
        this.age=mmt.getAge();
        this.salary=mmt.getSalary();
    }

    public Emp(String name, int age, double salary) {
        super();
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    
    

}

【備忘錄類】

/***
 * 備忘錄類
 */
package cn.sxt.memento;

public class EmpMemento {
    private String name;
    private int age;
    private double salary;
    

    public EmpMemento(Emp emp) {//傳入源發器對象,即備忘誰的信息
        this.name=emp.getName();//把雇員類的所有信息復制一遍給備忘錄類
        this.age=emp.getAge();
        this.salary=emp.getSalary();
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    

}

【管理備忘錄】

/***
 * 負責人類,負責管理備忘錄對象
 */
package cn.sxt.memento;

import java.util.ArrayList;
import java.util.List;

public class CareTaker {
    private EmpMemento memento;
    
    //private List<EmpMemento>list =new ArrayList<EmpMemento>(); 可以存多個備忘錄點,也可以搞搞個棧

    public EmpMemento getMemento() {
        return memento;
    }

    public void setMemento(EmpMemento memento) {
        this.memento = memento;
    }
    

}

【測試】

/**
 * 
 */
package cn.sxt.memento;


public class Client {
    public static void main(String[] args) {
        CareTaker taker=new CareTaker();
        Emp emp1=new Emp("Tom", 10, 7000);
        System.out.println("原始的信息:"+emp1.getName()+"--"+emp1.getAge()+"--"+emp1.getSalary());
        
        taker.setMemento(emp1.memento());//原始信息做了一次備份
        
        emp1.setAge(18);
        emp1.setSalary(9000);//對信息做了一次修改
        System.out.println("修改後的信息:"+emp1.getName()+"--"+emp1.getAge()+"--"+emp1.getSalary());
        
        emp1.recovery(taker.getMemento());//恢復信息到taker對象管理的備忘錄點
        System.out.println("恢復後的信息:"+emp1.getName()+"--"+emp1.getAge()+"--"+emp1.getSalary());
    }

}

[19/05/02-星期四] GOF23_行為型模式(狀態模式、觀察者模式、備忘錄模式)