Head First 设计模式
感受
- 使用模式最好的方式是“把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。”以往是代码复用,现在是经验复用。
第一招 策略模式
1.1 设计原则
- 找出应用中可能需要变化之处,把它们独立出来,不要和哪些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程。
- 多用组合,少用继承。
1.2 上🦆UML
DuckUML.png
1.3 上🦆代码
封装飞行行为
interface FlyBehavior {
void fly();
}
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("鸭子的飞行了");
}
}
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("鸭子不会飞");
}
}
language-Java
封装呱呱叫行为
interface QuackBehavior {
void quack();
}
public class Qucak implements QuackBehavior {
public void quack() {
System.out.println("鸭子呱呱叫");
}
}
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("鸭子吱吱叫");
}
}
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("不会叫");
}
}
language-Java
客户使用封装好的飞行和呱呱叫算法族
public abstract class Duck{
private FlyBehavior flyBehavior;
private QuackBehavior quackBehavior;
public void swim() {
System.out.println("鸭子会游泳");
}
public abstract void display();
public void performQuack() {
quackBehavior.quack();
}
public void performFly() {
flyBehavior.fly();
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior) {
this.quackBehavior = quackBehavior;
}
}
public class MallardDuck extends Duck {
public void display() {
System.out.println("gree duck");
}
}
language-Java
Test类
public class StrategymodeTest {
public static void main(String [] args) {
Duck d1 = new MallardDuck();
d1.setFlyBehavior(new FlyWithWings());
d1.performFly();
d1.setQuackBehavior(new Qucak());
d1.performQuack();
}
}
language-Java
输入结果
$ java StrategymodeTest
鸭子的飞行了
鸭子呱呱叫
第二招 观察者模式
2.1 设计原则
- 找出应用中可能需要变化之处,把它们独立出来,不要和哪些不需要变化的代码混在一起。
- 针对接口编程,而不是针对实现编程。
- 多用组合,少用继承。
- 为交互对象之间的松耦合设计而努力
2.2 上UML图

观察者模式.png
2.3 上代码
- 主题和观察者的接口
// 主题接口
interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObserver();
}
// 观察者接口
interface Observer {
void update(Subject o, Object arg);
}
language-Java
- 具体主题1
import java.util.ArrayList;
public class ConcreteSubject1 implements Subject{
private ArrayList<Observer> observers;
private ArrayList<String> arg;
private boolean changed = false;
public ConcreteSubject1() {
observers = new ArrayList<Observer>();
arg = new ArrayList<String>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObserver() {
if (changed) {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(this, arg);
}
changed = false;
}
}
protected void setChanged() {
changed = true;
}
public void setMeasurements(String data) {
arg.add(data);
notifyObserver();
}
}
language-Java
- 具体主题2
import java.util.ArrayList;
public class ConcreteSubject2 implements Subject{
private ArrayList<Observer> observers;
private ArrayList<String> arg;
private boolean changed = false;
public ConcreteSubject2() {
observers = new ArrayList<Observer>();
arg = new ArrayList<String>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObserver() {
if (changed) {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(this, arg);
}
}
}
protected void setChanged() {
changed = true;
}
public void setMeasurements(String data) {
arg.add(data);
notifyObserver();
}
}
language-Java
- 关注具体主题1的具体观察者1
public class ConcreteObserver1 implements Observer {
private Subject subject;
public ConcreteObserver1(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
public void update(Subject o, Object arg) {
System.out.println("我是观察者1,我的主题1更新了");
}
}
language-Java
- 关注具体主题1,2的具体观察者2
public class ConcreteObserver2 implements Observer {
private Subject subject1;
private Subject subject2;
public ConcreteObserver2(Subject subject1, Subject subject2) {
this.subject1 = (Subject)subject1;
this.subject2 = (Subject)subject2;
subject1.registerObserver(this);
subject2.registerObserver(this);
}
public void update(Subject o, Object arg) {
if (o instanceof ConcreteSubject1) {
System.out.println("我是观察者2,我的主题1更新了");
}
if (o instanceof ConcreteSubject2) {
System.out.println("我是观察者2,我的主题2更新了");
}
}
}
language-Java
- 关注具体主题2的具体观察者3
public class ConcreteObserver3 implements Observer {
private Subject subject;
public ConcreteObserver3(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
public void update(Subject o, Object arg) {
System.out.println("我是观察者3, 我的主题2更新了");
}
}
language-Java
- 测试代码
import java.util.ArrayList;
public class ObserverTest {
public static void main(String[] args) {
ConcreteSubject1 subject1 = new ConcreteSubject1();
ConcreteSubject2 subject2 = new ConcreteSubject2();
new ConcreteObserver1(subject1);
new ConcreteObserver2(subject1, subject2);
new ConcreteObserver3(subject2);
subject1.setChanged();
subject1.setMeasurements("test");
subject2.setMeasurements("test2");
}
}
language-Java
- 测试结果
$ java ObserverTest
我是观察者1,我的主题1更新了
我是观察者2,我的主题1更新了
我是观察者2,我的主题2更新了
我是观察者3, 我的主题2更新了
- java.util包实现了Observable类,也可以满足一些观察者的情况。首先,因为没有Observer接口,所以无法建立自己的实现,和Java内置的Observer API搭配使用。
第3招 装饰者模式
装饰纸模式:动态地将责任附加到对象上。想要扩展功能,装饰者提供有别于继承的另一种选择。
3.1设计原则
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合设计而努力
- 对扩展开发,对修改关闭
3.2上UML图
先决定那种咖啡,在决定使用什么配料。

装饰者模式.png
3.3上代码
- 定义饮料类,必须设置一个抽象方法。
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
language-Java
- 深烘咖啡,实现夫类的抽象方法。
public class DarkRoast extends Beverage {
public DarkRoast() {
description = "DarkRoast Coffee";
}
public double cost() {
return 1.19;
}
}
language-Java
- 定义装饰者。调味装饰者
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
language-Java
- 实现第一个一个装饰者。牛奶配料
public class Milk extends CondimentDecorator{
Beverage beverage;
public Milk(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Milk";
}
public double cost() {
return .10 + beverage.cost();
}
}
language-Java
- 实现第二个装饰者。摩卡配料
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Mocha";
}
public double cost() {
return .20 + beverage.cost();
}
}
language-Java
- 测试代码
public class StarbuzzCoffee {
public static void main(String[] args) {
// 没有配料的拿铁咖啡
Beverage beverage = new DarkRoast();
System.out.println(beverage.getDescription() + " $" + beverage.cost());
// 摩卡, 牛奶, 拿铁咖啡(DarkRoast)
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);
beverage2 = new Milk(beverage2);
System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
}
}
language-Java
- 运行结果
java StarbuzzCoffee
DarkRoast Coffee $1.19
DarkRoast Coffee, Mocha, Milk $1.49
第四招 工厂模式
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。
4.1设计原则
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合设计而努力
- 类应该对扩展开放,对修改关闭
- 依赖抽象,不要依赖具体类。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 hjxstart@126.com