• 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式


    装饰者模式是JDK中还有一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源代码,也是为了学习大牛们的设计思路。————题记

    设计模式
    观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时。它的全部依赖者都会受到通知并自己主动更新。

    装饰者模式:动态地将责任附加到对象上。

    若要扩展功能。装饰者提供比继承者更有弹性的替代方案。


    设计原则
    (1)封装变化。

    (2)多用组合,少用继承。
    (3)针对接口编程,而不是针对实现编程。

    (4)为了交互对象之间的松耦合设计努力。

    对象之间的像话依赖降到了最低。有助于简历有弹性的OO系统,可以应对变化。
    (5)类应该对扩展开发。对改动关闭。

    目标是同意类easy扩展,在不改动现有代码的情况下,就能够搭配出新的行为。


    要点
    观察者模式定义了对象之间一对多的关系。

    使用观察者模式时。能够从被观察者出推或拉数据。
    观察者模式中。会改变的是主题的状态。以及观察者的数量和类型。用这个模式,你能够改变依赖于主题状态的对象,却不必改变主题。
    继承属于扩展形式之中的一个,但不见得是达到弹性设计的最佳方式。
    组合和托付可用于执行时动态加上新的行为。
    装饰者能够在被装饰者的行为前面与或后面加上自己的行为。甚至代替,达到特有的目的。
    装饰者会导致设计中出现很多小对象。假设过度使用。会让小程序变得复杂。

    Java内置的观察者模式:Obverser接口与Obversable类。

    缺点:
    (1)Obversable是一个类,必须设计一个类继承他。假设想同一时候具有Obversable类和还有一个超类的行为,就会陷入两难。由于Java不支持多重继承。Obversable没有接口,无法建立自己的实现。
    (2)Obversable将setChange()方法保护起来了。这样一来。除非继承,否则无法创建Obversable实例并组合到自己的对象中来。

    真实世界的装饰者
    java.io包内的类太多了。简直是排山倒海。

    以下是一个典型的对象集合,用装饰者来将功能结合起来。以读取文件数据:

    超类:InputStream
    组件:FileInputStream、StringBufferInputStream、ByteArrayInputStream
    抽象装饰者:FilterInputStream
    详细装饰者:PushBackInputStream、BufferedInputStream、DataInputStream、LineNumberInputStream

    观察者模式:
    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 DispalyElement {
    	public void dispaly();
    }
    
    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();
    	}
    	
    	public void setMeasurements(float temperature, float humidity, float pressure) {
    		this.temperature = temperature;
    		this.humidity = humidity;
    		this.pressure = pressure;
    		measurementsChanged();
    	}
    	
    	public float getTemperature() {
    		return temperature;
    	}
    	
    	public float getHumidity() {
    		return humidity;
    	}
    	
    	public float getPressure() {
    		return pressure;
    	}
    }
    
    //測试代码
    public class WeatherStation {
    	public static void main(String[] args) {
    		WeatherData weatherData = new WeatherData();
    		
    		CurrentConditionsDisplay currentDisplay =
    		new CurrentConditionsDisplay(weatherData);
    		
    		weatherData.setMeasurements(80,65,30.4f);
    	}
    }
    



    装饰者模式:
    //抽象类
    public abstract class Beverage {
    	String description = "Unknown Beverage";
      
    	public String getDescription() {
    		return description;
    	}
     
    	public abstract double cost();
    }
    
    //CondimentDecorator必须能代替Beverage。所以将CondimentDecorator必须能代替Beverage。所以将扩展成Beverage类扩展成Beverage类
    public abstract class CondimentDecorator extends Beverage {
    	//全部调料装饰者必须又一次实现getDescription()方法
    	public abstract String getDescription();
    }
    
    //饮料代码扩展自Beverage
    public class Espresso extends Beverage {
      
    	public Espresso() {
    		description = "Espresso";
    	}
      
    	public double cost() {
    		return 1.99;
    	}
    }
    
    //装饰者
    public class Soy extends CondimentDecorator {
    	Beverage beverage;//记录被装饰者
    
    	public Soy(Beverage beverage) {
    		this.beverage = beverage;
    	}
    
    	public String getDescription() {
    		return beverage.getDescription() + ", Soy";
    	}
    
    	public double cost() {
    		return .15 + beverage.cost();
    	}
    }
    
    //測试代码
    public class StarbuzzCoffee {
     
    	public static void main(String args[]) {
    		Beverage beverage = new Espresso();
    		System.out.println(beverage.getDescription() 
    				+ " $" + beverage.cost());
     
    		Beverage beverage2 = new DarkRoast();
    		beverage2 = new Mocha(beverage2);//层层装饰
    		beverage2 = new Mocha(beverage2);
    		beverage2 = new Whip(beverage2);
    		System.out.println(beverage2.getDescription() 
    				+ " $" + beverage2.cost());
     
    		Beverage beverage3 = new HouseBlend();
    		beverage3 = new Soy(beverage3);
    		beverage3 = new Mocha(beverage3);
    		beverage3 = new Whip(beverage3);
    		System.out.println(beverage3.getDescription() 
    				+ " $" + beverage3.cost());
    	}
    }



  • 相关阅读:
    Mysql5.7 单表 500万数据迁移到新表的快速实现方案
    Jmeter5 实现多机集群压测(局域网组成多机集群)
    IDEA 配置datasource,提升编码效率,让你在 Mapper.xml 中编写sql可以飞起来~
    Logstash 6.4.3 导入 csv 数据到 ElasticSearch 6.4.3
    从零开始搭建一个从Win7环境备份至CentOS7的SVN双机备份环境
    实现logstash6.4.3 同步mysql数据到Elasticsearch6.4.3
    uEditor使用步骤
    动态添加a标签打开新网页
    vue给对象添加新的响应式属性
    vue下载excel
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5306727.html
Copyright © 2020-2023  润新知