1. 设计模式入门
设计模式不是代码的具体实现,它是解决某一类问题的通用设计方案。
设计模式的本质目的是:使软件工程在维护性、扩展性、变化性、复杂度方面成0(N)
OO设计是原则,设计模式是具体方法、工具。
例如:
在Java里IO流的类设计,为什么把BufferedReader设计成:
new BufferedReader(new FileReader(“F:\test.java”));
//而不是设计成:
BufferedReader extends FileReader;
new BufferedReader("F:\test.java");
2. 策略模式原理
2.1 模拟鸭子项目
2.1.1 从OO的角度设计这个项目
鸭子具有相同的叫声以及都会游泳,但是每只鸭子的颜色不同,比如说有绿头鸭,红头鸭等。
2.1.2 从OO的角度设计这个项目
- 1.设置鸭子超类
public abstract class SuperDuck {
//颜色让子类去具体实现
public abstract void display();
public void quack(){
System.out.println("~GaGa~");
}
public void swim(){
System.out.println("~In Swim~");
}
}
- 2.生成绿头鸭子类
public class GreenDuck extends SuperDuck {
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("~show Green Head~");
}
}
- 3.生成红头鸭子类
public class RedDuck extends SuperDuck {
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("~Show Red Head~");
}
}
使用OO基本满足了项目的需求。
2.2 项目的新需求
2.2.1 应对新的需求,看看这个设计的可扩展性
需求1)添加会飞的鸭子
在OO思维解决这个问题,使用:
在鸭子超类中添加这个方法:
public abstract class SuperDuck {
//颜色让子类去具体实现
public abstract void display();
public void quack(){
System.out.println("~GaGa~");
}
public void swim(){
System.out.println("~In Swim~");
}
public void fly(){
System.out.println("In Fly");
}
}
2.3 用OO原则解决需求的不足
问题出现:这个fly()让所有的鸭子都飞起来了,这是不科学的
继承问题:对类的局部的变动,尤其是超类的局部变动,会影响其他部分。影响会有溢出效应。
使用覆盖解决问题:
在子类中对超类的方法进行覆盖,在超类中,进行改动的话,必须在子类中进行全面的覆盖。(如果已经生成上千个子类?需要对这些子类重新进行初始化,这个方法并不可行)
需求2)添加石头鸭子,就需要对以上所有方法进行覆盖。
public class StoneDuck extends Duck{
}
超类挖的一个坑,每个子类都要填,增加工作量,复杂度O(N^2)
2.4 用策略模式来解决鸭子的项目
目的:使用新的设计模式,应对项目的扩展性,降低复杂度。
1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现;
2)鸭子哪些功能是会根据新需求变化的?叫声、 飞行…
解决方法:接口
public interface SuperFly();
public interface SuperQuack();
好处:新增行为简单,行为类更好的复用,组合更方便。 既有继承带来的复用好处,没有挖坑。
2.5 重新设计模拟鸭子项目
2.5.1 dx.com.quack(叫声实现)
- SuperQuack
package dx.com.quack;
public interface SuperQuack {
public void quack();
}
- Gaquack
package dx.com.quack;
public class Gaquack implements SuperQuack {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("~Ga~Ga~");
}
}
- GeQuack
package dx.com.quack;
public class GeQuack implements SuperQuack {
@Override
public void quack() {
// TODO Auto-generated method stub
System.out.println("~Ge~Ge~");
}
}
- NoQuack
package dx.com.quack;
import dx.com.stimulate.SuperDuck;
public class NoQuack extends SuperDuck {
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("~ ~ ~");
}
}
2.5.2 dx.com.quack(飞行实现)
- SuperFly
package dx.com.fly;
public interface SuperFly {
public void fly();
}
- NoFly
package dx.com.fly;
public class NoFly implements SuperFly {
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("NO Fly");
}
}
- GoodFly
package dx.com.fly;
public class GoodFly implements SuperFly{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("Good Fly");
}
}
- BadFly
package dx.com.fly;
public class BadFly implements SuperFly{
@Override
public void fly() {
// TODO Auto-generated method stub
System.out.println("Bad fly");
}
}
2.5.3 dx.com.duck
- SuperDuck
package dx.com.duck;
import dx.com.fly.SuperFly;
import dx.com.quack.SuperQuack;
public abstract class SuperDuck {
public SuperFly superFly;
public SuperQuack superQuack;
public SuperDuck() {
};
public abstract void display();
public void fly() {
superFly.fly();
}
public void quack() {
superQuack.quack();
}
public void setFly(SuperFly fly) {
this.superFly = fly;
}
public void setQuack(SuperQuack quack) {
this.superQuack = quack;
}
}
- GreenDuck
package dx.com.duck;
import dx.com.fly.GoodFly;
import dx.com.quack.Gaquack;
public class GreenDuck extends SuperDuck {
public GreenDuck(){
superFly = new GoodFly();
superQuack = new Gaquack();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("show green head");
}
}
- RedDuck
package dx.com.duck;
import dx.com.fly.BadFly;
import dx.com.quack.GeQuack;
import dx.com.quack.SuperQuack;
public class RedDuck extends SuperDuck{
public RedDuck(){
superFly = new BadFly();
superQuack = new GeQuack();
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("show red head");
}
}
2.6 总结策略模式定义
策略模式:分别封装行为借口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化备份,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者。
3. 策略模式注意点
- 1.分析项目中变化部分与不变部分
- 2.多用组合少用继承;用行为类组合,而不是行为的继承。更有弹性
- 3.设计模式有没有相应的库直接使用?有些库或框架本身就用某种设计模式设计的