把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。
每个设计模式背后的精神所在:
设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
如果每次新需求一来,都会使某些方面的代码发生变化,那么就可以确定,这部分的代码需要被抽出来,和其他稳定的代码有所区分。
把会变化的部分取出并封装起来,以便以后可以轻易的改动或扩充此部分,而不影响不需要变化的其它部分
鸭子模拟
所有的鸭子都会呱呱叫Quack,也会游泳Swim,所以由超类负责处理这部分的实现代码
每一种鸭子的外观都不同,所以display方法是抽象的
新需求:我们让有的鸭子可以飞起来
先在Duck类上加上fly方法,然后所有的鸭子都继承fly方法
问题来了:有的鸭子不会飞,但是也具有了飞这个行为,比如橡皮鸭子
在超类中加上了新的行为,使得某些不适合该行为的子类也具有了该行为,对代码的局部修改,影响层面可不是局部
继续按照这个继承这个思路去解决问题,可以覆盖fly方法,让fly方法什么都不做
问题又来了:如果以后加入木头鸭子,不会飞也不会叫。
很难知道鸭子的全部行为,每次新增子类,都要被迫检查各个行为
用接口来解决,但是首先是针对实现编程
我们可以把fly从超类中取出来,放到一个Flyable接口中,只有会飞的鸭子才实现此接口,同样的方式,也可以用来设计一个Quackable接口,只有会叫的鸭子才下实现这个接口
问题来了:
上面的接口设计造成了代码不能复用,每个子类都得在用到的时候实现接口
因为java接口不具有实现代码,所以继承接口无法达到代码复用
设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
系统中的某些改变不影响其它部分
我们现在知道Duck类内的fly和quack会随着鸭子的不同而改变,为了要把这两个行为从Duck类中分开,我们将把它们从Duck类中取出来,建立一组新类来代表每个行为。
设计原则:正对接口编程,而不是针对实现编程。
之前的行为来自于Duck超类的具体实现,或是继承某个接口并由子类自行实现而来。这两种做法都一来于实现。
先来看个简单的多态例子
我们不知道子类型是什么,我们只关心它知道如何正确的进行makeSound的动作就可以了
整体的格局
一组行为,一族算法
关系可以是
(是一个)
(有一个)
(实现)
设计原则:多用组合,少用继承
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户
下面,我们用代码来实现终极版类图
package com.alvin.strategy;
import com.alvin.strategy.behavior.FlyBehavior;
import com.alvin.strategy.behavior.QuackBehavior;
public abstract class Duck {
protected FlyBehavior flyBehavior;
protected QuackBehavior quackBehavior;
public void swim(){
System.out.println("swim");
}
abstract public void display();
public void setFlyBehavior(FlyBehavior flyBehavior){
this.flyBehavior = flyBehavior;
}
public void setQuackBehavior(QuackBehavior quackBehavior){
this.quackBehavior = quackBehavior;
}
public void performFly() {
flyBehavior.fly();
}
public void performQuack() {
quackBehavior.quack();
}
}
package com.alvin.strategy.subduck;
import com.alvin.strategy.Duck;
import com.alvin.strategy.behavior.impl.FlyWithWings;
import com.alvin.strategy.behavior.impl.Quack;
public class MallardDuck extends Duck{
public MallardDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Quack();
}
@Override
public void display() {
System.out.println("MallardDuck");
}
}
package com.alvin.strategy.subduck;
import com.alvin.strategy.Duck;
import com.alvin.strategy.behavior.impl.FlyWithWings;
import com.alvin.strategy.behavior.impl.Squeak;
public class RedheadDuck extends Duck {
public RedheadDuck(){
flyBehavior = new FlyWithWings();
quackBehavior = new Squeak();
}
@Override
public void display() {
System.out.println("RedheadDuck");
}
}
package com.alvin.strategy.behavior;
public interface FlyBehavior {
void fly();
}
package com.alvin.strategy.behavior;
public interface QuackBehavior {
void quack();
}
package com.alvin.strategy.behavior.impl;
import com.alvin.strategy.behavior.FlyBehavior;
public class FlyNoWay implements FlyBehavior{
@Override
public void fly() {
System.out.println("FlyNoWay");
}
}
package com.alvin.strategy.behavior.impl;
import com.alvin.strategy.behavior.FlyBehavior;
public class FlyWithWings implements FlyBehavior{
@Override
public void fly() {
System.out.println("FlyWithWings");
}
}
package com.alvin.strategy.behavior.impl;
import com.alvin.strategy.behavior.QuackBehavior;
public class MuteQuack implements QuackBehavior {
@Override
public void quack() {
System.out.println("MuteQuack");
}
}
package com.alvin.strategy.behavior.impl;
import com.alvin.strategy.behavior.QuackBehavior;
public class Quack implements QuackBehavior{
@Override
public void quack() {
System.out.println("Quack");
}
}
package com.alvin.strategy.behavior.impl;
import com.alvin.strategy.behavior.QuackBehavior;
public class Squeak implements QuackBehavior{
@Override
public void quack() {
System.out.println("Squeak");
}
}
package com.alvin.strategy;
import com.alvin.strategy.behavior.impl.Squeak;
import com.alvin.strategy.subduck.MallardDuck;
public class Run {
public static void main(String[] args) {
Duck duck = new MallardDuck();
duck.performFly();
duck.performQuack();
duck.setQuackBehavior(new Squeak());
duck.performQuack();
}
}
运行结果
FlyWithWings
Quack
Squeak
Quack
Squeak