《HeadFirst 设计模式》摘抄笔记,供以后查阅。
策略模式
定义
策略模式定义了算法族,分别进行封装,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
设计原则如下:
- 找出应用中可能变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起
- 针对接口编程,而不是针对实现编程
- 多用组合,少用继承
代码演示
不变属性
public abstract class Duck {
//不变属性可以直接写在超类中
//动态属性通过组合(has a)方式关联
private FlyBehavior flyBehavior;
private QuackBehavior quackBehavior;
public void performFly(){
flyBehavior.fly();
}
public void performQuack(){
quackBehavior.quack();
}
public abstract void display();
//......省略 setter 方法:可以通过该方法动态的设置行为......
}
public class MallardDuck extends Duck {
public MallardDuck() {
this.setFlyBehavior(new FlyWithWings());
this.setQuackBehavior(new Quack());
}
@Override
public void display() {
System.out.println("MallardDuck.class --> display");
}
}
动态属性
// 飞翔属性定义
public interface FlyBehavior {
public void fly();
}
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying!!!");
}
}
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly!!!");
}
}
// 叫声属性定义
public interface QuackBehavior {
void quack();
}
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack");
}
}
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("<< Silence >>");
}
}
执行测试代码
public class DuckDemoMain {
public static void main(String[] args) {
MallardDuck mallardDuck = new MallardDuck();
mallardDuck.performFly();
}
}
观察者模式
定义
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会通知并自动更新。
设计原则如下:
- 为了交互对象之间的松耦合设计而努力
核心接口
//主题
public interface Subject {
//观察者注册为主题的观察者
void registerObserver(Observer o);
//观察者将自己在主题观察者列表中移除
void removeObserver(Observer o);
//当主题状态改变时,通过该方法通知观察者
void notifyObserver();
}
//观察者
public interface Observer {
void update(float temp, float humidity, float pressure);
}
代码演示(推送方式)
场景说明
- 主题:气象站生成数据
- 观察者:布告板订阅数据并进行数据展示
代码实现
//业务代码公用行为抽取
public interface DisplayElement {
//数据展示
void display();
}
//气象站实现类
public class WeatherData implements Subject {
private final List<Observer> observerList;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
this.observerList = new ArrayList<>();
}
@Override
public void registerObserver(Observer o) {
observerList.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observerList.indexOf(o);
if (i >= 0) {
observerList.remove(i);
}
}
@Override
public void notifyObserver() {
for (Observer observer : observerList) {
observer.update(temperature, humidity, pressure);
}
}
//数据发生改变执行该动作
public void measurementsChanged(){
notifyObserver();
}
public void setMeasurements(float temperature,float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//......省略其他方法
}
//布告板实现
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);
}
@Override
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
@Override
public void display() {
String msg = String.format("CurrentConditionsDisplay -> temperature:%s、humidity:%s", temperature, humidity);
System.out.println(msg);
}
}
//测试类
public class Demo02Maina {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
//建立一个或多个公告板
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
//数据发生改动
weatherData.setMeasurements(1.0f, 1.0f, 1.0f);
}
}
Java 内置观察者模式
Java 中内置的观察者模式可以使用推送、拉取的方式。
核心接口
//主题:java.util.Observable
public class Observable {
public synchronized void addObserver(Observer o) { //......省略代码实现 }
public synchronized void deleteObserver(Observer o) { //......省略代码实现 }
public void notifyObservers() {
//......
if (!changed)
return;
//......
}
//用来控制粒度,只有将 changed 设置为 true,才会对观察者进行通知
protected synchronized void setChanged() {
changed = true;
}
//......
}
//观察者:java.util.Observer
public interface Observer {
void update(Observable o, Object arg);
}
代码实现
对气象站、布告板代码进行重写。
//业务代码公用行为抽取
public interface DisplayElement {
void display();
}
//气象站
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
}
//数据发生改变执行该动作
public void measurementsChanged(){
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature,float humidity, float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//getter 方法用于数据拉取
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 Observable observable;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if (o instanceof WeatherData) {
WeatherData weatherData = (WeatherData) o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
@Override
public void display() {
String msg = String.format("CurrentConditionsDisplay -> temperature:%s、humidity:%s", temperature, humidity);
System.out.println(msg);
}
}
//测试类
public class Demo03Main {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
//建立一个或多个公告板
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
//数据发生改动
weatherData.setMeasurements(2.0f, 5.0f, 1.0f);
}
}