装饰者模式是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());
}
}


《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式的更多相关文章

  1. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

  2. Java设计模式学习笔记(三) 工厂方法模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 简介 上一篇博客介绍了简单工厂模式,简单工厂模式存在一个很严重的问题: 就是当系统需要引入 ...

  3. Java设计模式学习笔记(四) 抽象工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 1. 抽象工厂模式概述 工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问 ...

  4. C#设计模式学习笔记:(12)代理模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/7814004.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲结构型设计模式的第七个模式,也是 ...

  5. C#设计模式学习笔记:(23)解释器模式

    本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8242238.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第十一个模式-- ...

  6. HeadFirst设计模式读书笔记(3)-装饰者模式(Decorator Pattern)

    装饰者模式:动态地将责任附件到对象上.若要扩展功能,装饰者提东了比继承更有弹性的替代方案. 装饰者和被装饰对象有相同的超类型 你可以用一个或者多个装饰者包装一个对象. 既然装饰者和被装饰对象有相同的超 ...

  7. Java-马士兵设计模式学习笔记-观察者模式-模拟Awt Button

    一.概述 Java 的Awt是 Observer模式,现用Java自己模拟awt中Button的运行机制 二.代码 1.Test.java import java.text.DateFormat; i ...

  8. Java-马士兵设计模式学习笔记-观察者模式-AWT简单例子

    1.AWT简单例子 TestFrame.java import java.awt.Button; import java.awt.Frame; import java.awt.event.Action ...

  9. Java-马士兵设计模式学习笔记-观察者模式-读取properties文件改成单例模式

    一.概述 1.目标:读取properties文件改成单例模式 二.代码 1.Test.java class WakenUpEvent{ private long time; private Strin ...

随机推荐

  1. htmilunit-- 针对抓取js生成的数据

    public static String  getHtml(String html){        // 模拟一个浏览器          @SuppressWarnings("resou ...

  2. BZOJ-3231 [SDOI2008]递归数列

    转成矩阵连乘后,矩阵快速幂加速解决. 一开始没把需要longlong的变量补全..而且没初始化2333 #include <cstdlib> #include <cstdio> ...

  3. hdu3586 Information Disturbing 【树形dp】

    题目链接 hdu3586 题解 二分 + 简单的树形dp 我正有练一下dp的必要了 #include<iostream> #include<cstdio> #include&l ...

  4. bzoj4030【HEOI2015】小L的白日梦

    题意:http://www.lydsy.com/JudgeOnline/problem.php?id=4030 sol  :orz Yousiki http://www.cnblogs.com/you ...

  5. [openmp]使用嵌套并行

    变量OMP_NESTED设置使其可以在函数中并行. #include "omp.h" #include <cstdio> #include <iostream&g ...

  6. h5 video切换到横屏全屏

    将video设置为屏幕大小,覆盖其他元素,想到这种操作我也是震惊的 function() { let startIcon = document.getElementById('start-icon') ...

  7. redis批量删除脚本

    服务器上安装了redis客户端,通过客户端利用脚本对数据批量删除,脚本内容如下: #!/bin/bash name="$1" echo $name ./redis-cli -h r ...

  8. HTTP Header中Accept-Encoding

    HTTP Header中Accept-Encoding 是浏览器发给服务器,声明浏览器支持的编码类型[1]  常见的有 Accept-Encoding: compress, gzip //支持comp ...

  9. 《手把手教你学C语言》学习笔记(10)--- 程序的循环控制

    C语言程序设计中,有些代码需要重复执行很多次,循环主要有三类: 一.for循环 1.基本格式为:for(表达式1:表达式2:表达式3){ //表达式1:循环变量赋初值 //表达式2:循环变量满足的条件 ...

  10. Python学习杂记_11_函数(一)

    函数也叫方法,就是把实现某种功能的一组代码封装起来,当你需要这个功能时直接调用函数即可. 定义函数:定义函数时要注意 “def”关键字,“:”,“函数体缩进”:用“return”使函数有具体返回值,没 ...