本书是本人写的设计模式的笔记,写下核心要点,如果你掌握过设计模式,想快速阅读本书内容,这个笔记适合你阅读。如果你是新手,有 java 基础和 oo 设计原则基础,你适合跟我一样从零阅读本书。
第一章 策略模式
本章要点:
- OO 原则:封装变化;多用组合少用继承;针对接口编程,不针对实现编程
- 策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,在策略模式定义了一系列算法或策略,并将每个算法封装在独立的类中,使得它们可以互相替换。
我对策略模式的理解:
解耦与职责分离
- 没有策略模式的设计中,通常会把多种行为写在同一个类里,用一堆
if-else
或者switch
来决定执行哪段逻辑。这样代码臃肿、可读性差,也不利于维护。 - 采用策略模式后,把每一种行为都做成一个独立的策略类,实现同一个接口。上下文(Context)只负责持有一个接口引用、并在适当的时候调用它。
public abstract class Duck {
// 上下文(Context)只负责持有一个接口引用、并在适当的时候调用它
protected FlyBahavior flyBahavior;
protected QuackBehavior quackBehavior;
public Duck(){
}
/**
* 鸭子飞行能力委托给行为接口
*/
public void performFly(){
flyBahavior.fly();
}
// 委托给行为接口
public void performQuack() {
quackBehavior.quack();
}
// ......
}
动态可替换与运行时灵活性
- 过向上下文注入不同的策略实例,或者在运行中调用
setStrategy()
,就能立刻改变程序的行为,而不用改动或重编译现有类。 - 这对需求常变、或者在不同场景下要使用不同算法的系统来说,提供了极大的灵活性。例如,同一个支付模块里,可以在支付宝、微信、银行卡之间动态切换支付策略。
符合开闭原则
- 单个策略类职责单一、代码量小,非常适合单元测试。
- 同样的策略也可以在不同的上下文中复用,比如在一个图像处理项目里,对同一张图片做不同滤镜,只要把滤镜算法抽成策略,就能在多个处理流程里共享。
本章有一个鸭子的实例,使用了策略模式实现
如下图,将鸭子的能力拆分并封装,组合到Duck类中,实现高内聚低耦合,灵活扩展鸭子的能力。另外在 Duck 类中有 setFlyBehavior() 和 setQuackBehavior 支持动态改变鸭子的行为。
贴上代码:
行为接口
// FlyBehavior.java
public interface FlyBehavior {
void fly();
}
// QuackBehavior.java
public interface QuackBehavior {
void quack();
}
行为实现类
// FlyWithWings.java —— 可以飞
public class FlyWithWings implements FlyBehavior {
@Override
public void fly() {
System.out.println("I'm flying with wings!");
}
}
// FlyNoWay.java —— 不能飞
public class FlyNoWay implements FlyBehavior {
@Override
public void fly() {
System.out.println("I can't fly.");
}
}
// Quack.java —— 正常叫声
public class Quack implements QuackBehavior {
@Override
public void quack() {
System.out.println("Quack!");
}
}
// Squeak.java —— 吱吱叫(橡皮鸭)
public class Squeak implements QuackBehavior {
@Override
public void quack() {
System.out.println("Squeak!");
}
}
// MuteQuack.java —— 沉默,不叫
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("<< Silence >>");
}
}
Duck 抽象类
// Duck.java
public abstract class Duck {
// 组合:持有行为接口引用
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public Duck() {}
// 委托给行为接口
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
// 动态设置行为
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) {
quackBehavior = qb;
}
// 每个具体鸭子必须实现自己的展示方法
public abstract void display();
}
鸭子实现类
// MallardDuck.java —— 绿头鸭,会飞会叫
public class MallardDuck extends Duck {
public MallardDuck() {
// 构造时注入具体行为
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a real Mallard duck!");
}
}
// RedheadDuck.java —— 红头鸭,会飞会叫
public class RedheadDuck extends Duck {
public RedheadDuck() {
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("I'm a real Redhead duck!");
}
}
// RubberDuck.java —— 橡皮鸭,不能飞,会吱吱叫
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Squeak();
}
@Override
public void display() {
System.out.println("I'm a rubber duck!");
}
}
// DecoyDuck.java —— 诱饵鸭,不能飞,不会叫
public class DecoyDuck extends Duck {
public DecoyDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new MuteQuack();
}
@Override
public void display() {
System.out.println("I'm a decoy duck!");
}
}
模拟测试鸭子各个功能
// MiniDuckSimulator.java
public class MiniDuckSimulator {
public static void main(String[] args) {
// 创建不同类型的鸭子
Duck mallard = new MallardDuck();
Duck redhead = new RedheadDuck();
Duck rubber = new RubberDuck();
Duck decoy = new DecoyDuck();
System.out.println("--- Mallard Duck ---");
mallard.display();
mallard.performFly();
mallard.performQuack();
System.out.println("\n--- Rubber Duck ---");
rubber.display();
rubber.performFly();
rubber.performQuack();
// 动态更改行为示例
System.out.println("\n--- Dynamic Behavior Change ---");
Duck model = new MallardDuck();
model.display();
model.performFly(); // 默认:用翅膀飞
// 给模型鸭装上火箭
model.setFlyBehavior(new FlyNoWay() {
@Override
public void fly() {
System.out.println("I'm flying with a rocket!");
}
});
model.performFly(); // 现在会“火箭飞”
}
}