HeadFirst设计模式笔记(一)策略模式,观察者模式

18 篇文章 0 订阅
13 篇文章 1 订阅

1. 设计原则

  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
  3. 多样组合,少用继承。
  4. 为了交互对象之间的松耦合设计而努力。
  5. 类应该对扩展开放,而对修改封闭。

2. 设计模式

1. 策略模式

1.1 定义:

策略模式定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

1.2 鸭子模拟器案例:

这里写图片描述
这里应用了前两个设计原则。不同鸭子会有不同的飞行行为,不同的鸭子会有不同的呱呱叫行为,这些是需要变化的代码,所以独立出来;把鸭子的飞行行为和呱呱叫行为分别抽象为两个行为接口,设计不同鸭子采用接口不同的实现类。

1.3 示例代码

fly行为
//  飞行接口 
public interface FlyBehavior {  
public void fly();  
}  
//  飞 
public class FlyWithWings implements FlyBehavior{  
public void fly() {  
        System.out.println("正在用翅膀飞行");  
    }  
}  
//  不飞 
public class FlyNoWay implements FlyBehavior{  
public void fly() {  
        System.out.println("不会飞");  
    }  
}  
//坐火箭飞 
public class FlyRocketPowered implements FlyBehavior{  
public void fly() {  
        System.out.println("坐火箭飞");  
    }  
}  
quack行为
//  叫接口 
public interface QuackBehavior {  
public void quack();  
}  
// 嘎嘎叫 
public class Quack implements QuackBehavior. {  
public void quack() {  
        System.out.println("嘎嘎叫");  
    }  
}  
//  吱吱叫 
public class Squeak implements QuackBehavior{  
public void quack() {  
        System.out.println("吱吱叫");  
    }  
}  
//  不叫 
public class MuteQuack implements QuackBehavior{  
public void quack() {  
        System.out.println("不会叫");  
    }  
} 
实现Duck类  
//  鸭子超类
public abstract class Duck {  
//  默认的行为 
FlyBehavior flyBehavior;  
    QuackBehavior quackBehavior;  

public Duck() {  
    }  
public void setFlyBehavior(FlyBehavior. fb) {  
        flyBehavior = fb;  
    }  
public void setQuackBehavior(QuackBehavior. qb) {  
        quackBehavior = qb;  
    }  
abstract void display();  
public void performFly() {  
        flyBehavior.fly();  
    }  
public void performQuack() {  
        quackBehavior.quack();  
    }  
public void swim() {  
        System.out.println("正在游泳~~");  
    }  
}  

//  野鸭  
     public class MallardDuck extends Duck {  
     public MallardDuck() {  
         quackBehavior = new Quack();  
                 flyBehavior = new FlyWithWings();  //这里也可以使用setFlyBehavior方法,下同!
     }  
     public void display() {  
         System.out.println("绿头鸭");  
     }  
}  
     //  红头鸭  
     public class RedHeadDuck extends Duck {  
     public RedHeadDuck() {  
         flyBehavior = new FlyWithWings();  
         quackBehavior = new Quack();  
     }  
     public void display() {  
         System.out.println("红头鸭");  
     }  
}  
     //  橡皮鸭  
    public class RubberDuck extends Duck {  
     public RubberDuck() {  
         flyBehavior = new FlyNoWay();  
         quackBehavior = new Squeak();  
     }  
     public void display() {  
         System.out.println("橡皮鸭");  
     }  
}  
     //模型鸭  
public class ModelDuck extends Duck {  
     public ModelDuck() {  
         flyBehavior = new FlyNoWay();  
         quackBehavior = new Quack();  
     }  
     public void display() {  
         System.out.println("模型鸭");  
     }  
}  

/*测试代码:*/

public class MiniDuckSimulator {  

public static void main(String[] args) {  

        MallardDuck    mallard = new MallardDuck();  
        RubberDuck    rubberDuckie = new RubberDuck();  
        RedHeadDuck    redHeadDuck = new RedHeadDuck();  

        ModelDuck    model = new ModelDuck();  

        mallard.performQuack();  
        rubberDuckie.performQuack();  
        redHeadDuck.performQuack();  

        model.performFly();      
        model.setFlyBehavior(new FlyRocketPowered());  
        model.performFly();  
    }  
}  

2. 观察者模式

2.1 定义:

观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。

2.2 气象站发布气象布告栏订阅信息显示案例:

这里写图片描述
这里气象站是主题(Subject,或者叫做Observabler)类比于出版者,是事件发生的主体,布告栏是订阅者改称为观察者(Observer),是响应事情发生的主体。这里是一个一对多关系。模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新,这样的模式让主题和观察者之间松耦合。它体现了第四个原则:为了交互对象之间的松耦合设计而努力。

2.3.1 首先定义接口,实现这两个接口的类就是相应的主题类–气象搜集装置以及观察者类–对应气象发布版:

// 在主题接口中定义注册删除通知观察者三个方法
public interface Subject { 
    public void registerObserver(Observer o); 
    public void removeObserver(Observer o); 
    public void notifyObservers(); 
}
// 在观察者中,我们要求有一个方法:更新气象发布版的数据。
public interface Observer { 
    public void update(float temp, float humidity, float pressure); 
}
// 另外,每个布告板需要显示信息,定义第三个显示接口
public interface DisplayElement { 
    public void display(); 
}

2.3.2 接口实现以及测试

public class WeatherData implements Subject { 
    private ArrayList observers;//维护一个观察者列表 
    private float temperature; 
    private float humidity; 
    private float pressure; 
    public WeatherData() { 
        observers = new ArrayList(); //为了记住观察者而维护的列表,类比于报刊发行部门的订阅者列表 
    } 
    public void registerObserver(Observer o) { 
        observers.add(o); 
    } 
    public void removeObserver(Observer o) { 
        int i = observers.indexOf(o); 
        if (i >= 0) { 
            observers.remove(i); 
        } 
    } 
    public void notifyObservers() { //这个方法对所有注册的观察者进行通知 
        for (int i = 0; i < observers.size(); i++) { 
            Observer observer = (Observer)observers.get(i); 
            observer.update(temperature, humidity, pressure); //推数据 
        } 
    } 
    public void measurementsChanged() { //这个方法是对notifyObservers的封装 
        notifyObservers(); 
    } 
    public void setMeasurements(float temperature, float humidity, float pressure) { 
        this.temperature = temperature; 
        this.humidity = humidity; 
        this.pressure = pressure; 
        measurementsChanged();//这个方法会进而去通知所有的观察者 
    } 
    // other WeatherData methods here 
    public float getTemperature() { 
        return temperature; 
    } 
    public float getHumidity() { 
        return humidity; 
    } 
    public float getPressure() { 
        return pressure; 
    } 
}


/*我们再根据观察者接口实现多种气象发布版,这里只举出一个例子,其余大同小异:*/
public class CurrentConditionsDisplay implements Observer, DisplayElement { 
    private float temperature; 
    private float humidity; 
    private Subject weatherData;//维护一个主题的引用,注册观察者所用 
    public CurrentConditionsDisplay(Subject weatherData) { 
        this.weatherData = weatherData; 
        weatherData.registerObserver(this);//创建的时候就注册,这里也可以不进行这个,而使用 WeatherData 的registerObserver公有方法 
    } 
    public void update(float temperature, float humidity, float pressure) { //观察者留出的推送接口 
        this.temperature = temperature; 
        this.humidity = humidity; 
        display(); 
    } 
    public void display() { 
        System.out.println("Current conditions: " + temperature 
            + "F degrees and " + humidity + "% humidity"); 
    } 
}

/*我们测试一下这个程序:*/
public class WeatherStation {
    public static void main(String[] args) { 
        WeatherData weatherData = new WeatherData(); 
        CurrentConditionsDisplay currentDisplay = 
            new CurrentConditionsDisplay(weatherData); 
        StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData); 
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
        weatherData.setMeasurements(80, 65, 30.4f); 
        weatherData.setMeasurements(82, 70, 29.2f); 
        weatherData.setMeasurements(78, 90, 29.2f); 
    } 
}

2.3.3 java内置观察者模式

java内置的主题是一个类:Observable
java内置的观察者是接口:Observer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值