1、观察者模式
1)定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所以依赖者都会受到通知并自动更新。
解释:
a)观察者模式定义了一系列对象之间的一对多关系
b)当一个对象改变状态,其他依赖者都会受到通知
c)一个对象通常指主题,依赖者被称为许多观察者
d)例如报纸出版社与订阅者的关系
2)事例
观察者统一接口:IObserver.java
/**
观察者统一接口
* 所有的观测者都实现该接口 观察者实现该接口
*/
public interface IObserver {
/**
* 更新
*/
public void update(float temp, float humidity, float pressure);
}
主题接口:ISubject.java
/**
*主题接口 主题实现该接口
*/
public interface ISubject {
/**
* 观测者注册方法
*/
public void registerObserver(IObserver o)
/**
* 观测者取消方法
*/
public void removeObserver(IObserver o);
/**
* 主题状态改变时 通知所以的观察者
*/
public void notifyObservers()
}
主题实现类:WeatherData.java
/**
* @author one3c-zanpengfei
* 主题
*/
public class WeatherData implements ISubject {
private List observers;
private float temperature;
private float humidity;
private float pressure;
/**
* 该类在启动时被调用,创建一个list集合 保存观察者
*/
public WeatherData() {
observers = new ArrayList();
}
/**
* 注册方法,观察者注册是调用该接口
* @param o观察者
*/
@Override
public void registerObserver(IObserver o) {
observers.add(o);
}
/**
* 取消方法 观察者取消关注接口
* @param o 观察者
*/
@Override
public void removeObserver(IObserver o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
/**
* 主题通知方法 通知所有的观察者
*/
@Override
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
IObserver o = (IObserver) observers.get(i);
o.update(temperature, humidity, pressure);
}
}
/**
* 主题状态改变后 调用该方法
*/
public void measurementsChanged() {
notifyObservers();
}
/**
* 获取数据来源
* @param temperature温度
* @param humidity湿度
* @param pressure 气压
*/
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
观察者实现类:CurrentConditionDisplay.java
/**
* @author one3c-zanpengfei 布告板 观察者
*/
public class CurrentConditionDisplay implements IObserver, IDisplayElement {
private float temperature;
private float humidity;
private float pressure;
private ISubject weatherData;
public CurrentConditionDisplay(ISubject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
@Override
public void display() {
System.out
.println("Current conditions : " + temperature + "F degress and " + humidity + "%humidity and " + pressure +"%pressure");
}
}
测试类:WeatherStation.java
/**
* @author one3c-zanpengfei 测试类
*/
public class WeatherStation {
public static void main(String[] args) {
WeatherData whether = new WeatherData();
new CurrentConditionDisplay(whether);
whether.setMeasurements(80, 65, 30.4f);
whether.setMeasurements(70, 60, 38.4f);
whether.setMeasurements(90, 40, 25.4f);
}
}
运行测试类,打印结果:
Current conditions : 80.0F degress and 65.0%humidity and 30.4%pressureCurrent conditions : 70.0F degress and 60.0%humidity and 38.4%pressureCurrent conditions : 90.0F degress and 40.0%humidity and 25.4%pressure |
2、装饰着模式:
1)定义:动态地将责任附加到对象上,若要扩展功能,装饰着提供了比继承更有弹性的替代方案。
2)解释:
a)装饰着、被装饰着要继承同一个抽象类,继承达到“类型匹配”,而不是用继承获取“行为”。
b)依赖继承,那么类的行为只能在编译时静态决定,换句话说,行为如果不是来自超类,就是子类覆盖后的版本,反之,利用组合,可以把装饰着混合着用,而且是在“运行时”。
c)组合和委托可用在运行时动态的加上新的行为。
d)装饰着意味着一群装饰着类,这些类用来包装具体组件(被装饰着),可以用多个装饰着包装一个组件。
e)装饰着可以在被装饰着的行为前与后加上自己的行为,甚至将整个装饰着的行为整个取代掉,已达到特定的目的。
f)缺点:装饰着会导致设计中出现多个小对象,如果过度使用,会让程序变得复杂。
3)代码示例:要生成浓缩咖啡、黑咖啡+单分摩卡、黑咖啡+双方摩卡
饮料基类:Beverage.class
/**
* @author one3c-zanpengfei 饮料抽象类
*/
public abstract class Beverage {
String description = "Unknow Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
调料基类:CondimentDecorator.class
/**
* @author one3c-zanpengfei 调料抽象类
*/
public abstract class CondimentDecorator extends Beverage {
//所有调料装饰着必须实现该方法
public abstract String getDescription();
}
具体饮料-浓缩咖啡: Espresso.class
/**
* @author one3c-zanpengfei
* 饮料-浓缩咖啡类
*/
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
@Override
public double cost() {
return 1.99;
}
}
具体饮料-黑咖啡:HouseBlend.class
/**
* @author one3c-zanpengfei
* 饮料-黑咖啡类
*/
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "HouseBlend";
}
@Override
public double cost() {
return 0.99;
}
}
具体调料-摩卡:Mocha.class
/**
* @author one3c-zanpengfei 调料装饰着-摩卡,扩展至调料
*/
public class Mocha extends CondimentDecorator {
//被装饰着
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
/**
* 描述
*/
@Override
public String getDescription() {
return beverage.getDescription() + " , Mocha";
}
/**
* 价格
*/
@Override
public double cost() {
return .20 + beverage.cost();
}
}
测试类:StarbuzzCoffee.class
/**
* @author one3c-zanpengfei
* 测视-单个浓缩
* 测试-黑咖啡+单份mocha
* 测试-黑咖啡+双份mocha
*/
public class StarbuzzCoffee {
public static void main(String args[]){
//只要单个浓缩咖啡
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
//黑咖啡+2分摩卡调料
Beverage beverage1 = new HouseBlend();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);
System.out.println(beverage1.getDescription() + " $" + beverage1.cost());
}
}
4)总结:装饰着与被装饰着的基类继承共同的抽象类Beverage.class,是为了拥有共同的类型,而不是行为
5)原则:多扩展开放,对修改关闭;多用组合,少用继承