设计模式

策略模式

设计模式的用途在于,去弥补语言设计中的一些缺陷和不太好的地方

一个栗子

栗子来自于HeadFirst 设计模式

  • 有一个模拟鸭子的应用

    这个鸭子呢,有一个鸭子父类,还有无数的鸭子子类;

1
2
3
4
5
public class Duck{
public void quack(){}
public void swim(){}
public void display(){}
}
1
2
3
4
5
6
7
public class MallardDuck extends Duck{
public void display(){}
}
public class RedHeadDuck extends Duck{
public void display(){}
}

  • 后期又在这个基类的基础上加上一个fly()方法
1
2
3
4
5
6
7
public class Duck{
public void quack(){}
public void swim(){}
public void display(){}
...
public void fly(){}
}

但是如此一来,会使得,所有的子类都继承fly方法;但是不一定每一种duck都会fly呀!!!


这时候,可以让子类覆盖父类的fly方法;

1
2
3
4
5
6
7
8
9
public class MallardDuck extends Duck{
public void display(){}
public void fly(){}
}
public class RedHeadDuck extends Duck{
public void display(){}
public void fly(){}
}

没有fly方法的鸭子可以选择直接覆盖父类的fly方法,并且什么事都不做

  • But,这样的话,难道不会使得代码在多个子类中重复吗!!
  • 并且运行时行为为不容易改变

  • 换一种实现方式,让行为改用接口实现
1
2
3
4
5
6
7
public interface Flyable{
fly();
}
public interface Quackable{
quack();
}
1
2
3
4
5
6
7
8
9
10
11
12
public class MallardDuck extends Duck
implement Flyable,Quackable{
public void display(){}
public void fly(){}
public void quack(){}
}
public class RubberDuck extends Duck
implement Quackable{
public void display(){}
public void quack(){}
}

还是很麻烦啊!!!要写好多重复代码了啊混蛋!!!


写书的大叔说,要CHANGE;

  • 要将会变化的部分取出来并“封装”起来,让其他部分不受影响!

感觉这句很关键;将会变化的部分取出单独进行封装的话,那么有一些代码需要变动的时候,就不需要伤筋动骨,只需要去添加或修改取出的部分就可以了;

  • 找出应用中可能需要变化之处,把他们独立出来,不要和那些不需要变化的代码混在一起

策略模式

  • 个人理解:

    策略模式,像是将每一类的功能做成一组组件,每一组组件对应的是机器所需要的某一个部件的不同零件;就好比,兵哥哥配了不同的枪,就有不同的功能一样;

eg:

1
2
3
4
5
6
7
8
9
10
11
public interface FlyBehacior{
fly();
}
public class FlyWithWings{
fly(){}
}
public class FlyNoWay{
fly(){}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public interface QuackBehavior{
quack();
}
public class Quack{
quack(){}
}
public class Squack{
quack(){}
}
public class MuteeQuack{
quack(){}
}

实现eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Duck{
FlyBehavior flyBehavior;
QuackBehavior quackBehavior;
public void perormQuack(){
quackBehavior.quack();
}
public void swim(){}
public void display(){}
public void performFly(){
flyBehavior.fly();
}
}
public class MallardDuck extends Duck{
public MallardDuck(){
quackBehavior = new Quack();
flyBehavior = new FlayWithWings();
}
}

策略模式的另一个栗子

一个从网上找到的栗子

1
2
3
4
5
6
package com.zhy.bean;
public interface IAttackBehavior
{
void attack();
}
1
2
3
4
5
6
package com.zhy.bean;
public interface IDefendBehavior
{
void defend();
}
1
2
3
4
5
6
package com.zhy.bean;
public interface IDisplayBehavior
{
void display();
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.zhy.bean;
public class AttackJY implements IAttackBehavior
{
@Override
public void attack()
{
System.out.println("九阳神功!");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.zhy.bean;
public class DefendTBS implements IDefendBehavior
{
@Override
public void defend()
{
System.out.println("铁布衫");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
package com.zhy.bean;
public class RunJCTQ implements IRunBehavior
{
@Override
public void run()
{
System.out.println("金蝉脱壳");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.zhy.bean;
/**
* 游戏的角色超类
*
* @author zhy
*
*/
public abstract class Role
{
protected String name;
protected IDefendBehavior defendBehavior;
protected IDisplayBehavior displayBehavior;
protected IRunBehavior runBehavior;
protected IAttackBehavior attackBehavior;
public Role setDefendBehavior(IDefendBehavior defendBehavior)
{
this.defendBehavior = defendBehavior;
return this;
}
public Role setDisplayBehavior(IDisplayBehavior displayBehavior)
{
this.displayBehavior = displayBehavior;
return this;
}
public Role setRunBehavior(IRunBehavior runBehavior)
{
this.runBehavior = runBehavior;
return this;
}
public Role setAttackBehavior(IAttackBehavior attackBehavior)
{
this.attackBehavior = attackBehavior;
return this;
}
protected void display()
{
displayBehavior.display();
}
protected void run()
{
runBehavior.run();
}
protected void attack()
{
attackBehavior.attack();
}
protected void defend()
{
defendBehavior.defend();
}
}

每个角色现在只需要一个name了:

1
2
3
4
5
6
7
8
9
10
package com.zhy.bean;
public class RoleA extends Role
{
public RoleA(String name)
{
this.name = name;
}
}

Test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.zhy.bean;
public class Test
{
public static void main(String[] args)
{
Role roleA = new RoleA("A");
roleA.setAttackBehavior(new AttackXL())//
.setDefendBehavior(new DefendTBS())//
.setDisplayBehavior(new DisplayA())//
.setRunBehavior(new RunJCTQ());
System.out.println(roleA.name + ":");
roleA.run();
roleA.attack();
roleA.defend();
roleA.display();
}
}

面对接口编程而不是面对实现编程

利用了Java语言中的多态

编程时针对超类型(父类)进行编程,也就是说变量的声明类型(或方法的返回类型)是超类型,而不是具体的某个子类

超类型中的各个方法的具体实现不在超类型中,而是在各个子类中

这样在程序执行时可以根据实际状况执行到真正的(某个子类)行为

这是解耦合(松耦合)的思想。我们之后维护的时候可以随时将声明的变量替换为真正需要要执行的类型,具有很高的可维护性和可扩展性