设计模式之观察者、装饰者

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zanpengfei/article/details/86303783

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)原则:多扩展开放,对修改关闭;多用组合,少用继承

猜你喜欢

转载自blog.csdn.net/zanpengfei/article/details/86303783