设计模式学习(一)之策略模式

把模式装进脑子里,然后在你的设计和已有的应用中,寻找何处可以使用它们。
每个设计模式背后的精神所在:
设计原则:找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起
如果每次新需求一来,都会使某些方面的代码发生变化,那么就可以确定,这部分的代码需要被抽出来,和其他稳定的代码有所区分。
把会变化的部分取出并封装起来,以便以后可以轻易的改动或扩充此部分,而不影响不需要变化的其它部分

鸭子模拟
所有的鸭子都会呱呱叫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




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章