设计模式笔记_一_策略模式
简介
Head First 设计模式笔记。
相关概念
OO:面向对象,将问题看成一个系统,将系统按要素进行分类,并建立联系
OOD:面向对象设计
OOP:面向对象编程
策略模式
在超类中加上新的行为,会使得某些不适合该行为的子类也具有该行为。
利用继承来提供行为,造成的问题:
代码在多个子类中重复
运行时的行为不易改变
改变会牵一发动全身
很难知道各个子类行所具有的行为(由于子类会覆盖超类行为)
找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
把会变化的部分取出并“封装”起来,好让其他部分不会受到影响
针对接口编程
针对接口编程,而不是针对实现编程。
“针对接口编程” 真正的意思是 “针对超类型编程”。
这里所谓的“接口”有多个含义,接口是一个“概念”,也是一种Java的interface构造。你可以在不涉及Java interface的情况下,“针对接口编程”,关键就在多态。利用多态,程序可以针对超类型编程,执行时会根据实际状况执行真正的行为,不会被绑死在超类型的行为上。
“针对超类型编程”这句话,可以更明确地说成:“变量的声明类型应该是超类型,通常是一个抽象类或是一个接口,如此,只要是具体实现此超类型的类所产生的对象都可以指定给这个变量。这也意味着,声明类时不用了理会以后执行时的真正对象类型。”
一个简单多态的例子:
假设有一个抽象类Animal,有两个具体实现(Dog和Cat)集成Animal
#### 针对实现编程
Dog dog = new Dog(); // 类型声明d为Dog类型,会造成必须针对具体实现编程
d.bark(); // bark:叫声的一种
#### 针对借口编程如下
Animal animal = new Animal();
animal.makeSound(); // 利用animal进行多态调用
更棒的是,子类实例化的动作不再需要在代码中硬编码,而是“在运行时才指定具体实现的对象”,例如:
a = getAnimal();
a.makeSound();
整合的代码:
// FlyBehavior.java
public interface FlyBehavior {
public void fly();
}
// FlyWithWings.java
public class FlyWithWings implements FlyBehavior {
public void fly() {
System.out.println("I am flying!");
}
}
// FlyNoWay.java
public class FlyNoWay implements FlyBehavior {
public void fly() {
System.out.println("I can't fly!");
}
}
// QuackBehavior.java
public interface QuackBehavior {
public void quack();
}
// Quack.java
public class Quack implements QuackBehavior {
public void quack() {
System.out.println("Quack");
}
}
// MuteQuack.java
public class MuteQuack implements QuackBehavior {
public void quack() {
System.out.println("<< Silence >>);
}
}
// Squeak.java
public class Squeak implements QuackBehavior {
public void quack() {
System.out.println("Squeak");
}
}
// Duck.java
public abstract class Duck {
FlyBehavior flyBehavior; // 为行为接口类型声明两个引用变量,所有鸭子子类都继承他们
QuackBehavior quackBehavior;
public Duck() { }
public abstract void display();
public void performFly() {
flyBehavior.fly(); // 委托给行为类
}
public void performQuack() {
quackBehavior.quack(); // 委托给行为类
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
// MallardDuck.java
public class MallardDuck extends Duck {
public MallardDuck() {
quackBehavior = new Quack();
flyBehavior = new FlyWithWings();
}
public void display() {
System.out.println("I am a real Mallard duck");
}
}
// Output
bovenson@ThinkCentre:/home/public/Git/notes/DesignPattern/Code$ javac MiniDuckSimulator.java && java MiniDuckSimulator
Quack
I am flying!
动态设定行为
相较于面向过程思维(使用回调函数,调用同一方法表现出不同行为),使用动态链接方法更符合面向对象设计。
修改Duck.java
,添加setFlyBehavior(FlyBehavior fb)
和setQuackBehavior(QuackBehavior qb)
方法。
public abstract class Duck {
FlyBehavior flyBehavior; // 为行为接口类型声明两个引用变量,所有鸭子子类都继承他们
QuackBehavior quackBehavior;
public Duck() { }
public abstract void display();
public void performFly() {
flyBehavior.fly(); // 委托给行为类
}
public void performQuack() {
quackBehavior.quack(); // 委托给行为类
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
public void setFlyBehavior(FlyBehavior fb) { // 动态设定行为
flyBehavior = fb;
}
public void setQuackBehavior(QuackBehavior qb) { // 动态设定行为
quackBehavior = qb;
}
}
添加:
ModelDuck.java
FlyRocketPowered.java
// ModelDuck.java
public class ModelDuck extends Duck {
public ModelDuck() {
flyBehavior = new FlyNoWay();
quackBehavior = new Quack();
}
public void display() {
System.out.println("I'm a model duck");
}
}
// FlyRocketPowered.java
public class FlyRocketPowered implements FlyBehavior {
public void fly() {
System.out.println("I'm flying with a rocket!");
}
}
修改MiniDuckSimulator.java
public class MiniDuckSimulator {
public static void main(String args[]) {
Duck mallard = new MallardDuck();
mallard.performQuack();
mallard.performFly();
Duck model = new ModelDuck();
model.performFly();
model.setFlyBehavior(new FlyRocketPowered()); // 动态设定行为
model.performFly();
}
}
输出:
bovenson@ThinkCentre:/home/public/Git/notes/DesignPattern/Code$ cd "/home/public/Git/notes/DesignPattern/Code/Char0/" && javac MiniDuckSimulator.java && java MiniDuckSimulator
Quack
I am flying!
I can't fly!
I'm flying with a rocket!

组合
组合:将多个类结合起来使用。
这种做法和继承不同的地方在于,行为不是继承来的,而是和适当的行为对象组合来的。
多用组合,少用继承。虽然继承更加简单,可以加快开发,但是不利于后期维护。
定义
策略模式定义了算法簇,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
建立可维护的OO系统,要诀就在于随时想到系统以后可能需要的变化以及应付变化的原则。
总结
可用的工具
基础
抽象
封装
多态
继承
原则
封装变化
多用组合,少用继承
针对接口编程,不针对实现编程
模式
策略模式
要点
知道OO基础,并不足以设计出良好的OO系统
良好的OO设计必须具备可复用、可扩充、可维护三个特性
模式可以让我们建造出具有良好OO设计质量的系统
模式被认为是历经验证的OO设计经验
模式不是代码,而是针对设计问题的通用解决方案。你可把它们应用到特定的应用中。
模式不是被发明,而是被发现。
大多数的模式和原则,都着眼于软件变化的主题
大多数的模式都被允许系统局部改变独立于其他部分
常把系统中会变化的部分抽出来封装
模式让开发人员之间有共享的语言,能够最大化沟通的价值
最后更新于
这有帮助吗?