如果想要更加详细的 Java中的23种设计模式视频资源,请点击链接:Java中的23种设计模式视频资源下载
1、策略模式原理:
而按照面向对象编程(OO)的处理方式,实现不同的行为需要通过继承或者实现接口的方式来实现不同的行为,但是一旦加入新的行为或者功能,每个实现/继承的子类都需要做出相应的方法实现,复杂度为N^2.
把不同行为分别封装为接口,具体行为对象(实例)实现具体的行为接口来实现算法族 ;超类中方行为接口对象,在子类中定义具体行为对象。总的原则就是:分离出来变化部分,针对不同类型的变化部分封装成不同的接口,并基于这些接口实现不同的行为实现不同的行为算法。此模式让行为算法的实现独立于算法的调用者,最大程度上降低了编程的复杂度(N)。
2、案例:
以实现不同动物的发声方式和行走方式为例。
2.1 传统面向对象编程实现方式如下:
首先创造一个超类,内部包含两个方法,发声和移动package com.beBianMin.shareLogger.animal;
/**
* 动物超类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public abstract class Animal {
/**
* 发声方式
*/
abstract void sound();
/**
* 移动方式
*/
abstract void move();
}
然后不同的子类实现这个超类,并重载这两个方法
鸡的实现类package com.beBianMin.shareLogger.animal;
/**
* 鸡的实现类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*/
public class Chicken extends Animal{
@Override
void sound() {
System.out.println("咯咯咯咯.....");
}
@Override
void move() {
System.out.println("两条爪子走路,还会飞....");
}
}
鱼的实现类package com.beBianMin.shareLogger.animal;
/**
* 鱼的实现类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*/
public class Fish extends Animal{
@Override
void sound() {
System.out.println("我不会叫。。。。");
}
@Override
void move() {
System.out.println("水里游泳...");
}
}
测试类如下:package com.beBianMin.shareLogger.animal;
public class TestMain {
public static void main(String[] args) {
Animal chicken = new Chicken();
Animal fish = new Fish();
chicken.sound();
chicken.move();
fish.sound();
fish.move();
}
}
运行结果如下:咯咯咯咯.....
两条爪子走路,还会飞....
我不会叫。。。。
水里游泳...
以上方式就是通过面向对象编程的方式实现的不同行为(发声和移动),加入实现类很多,一旦需要扩展功能,比如新增一个行为(如何呼吸),那么我们不但需要在超类中写这个行为接口,还需要在所有的子类中实现这个接口,复杂度为N^2。
2.2 使用策略设计模式编程
策略模式就是要在面向对象编程过程中变化的行为类型那部分算法抽离出来,形成行为蔟,和调用者的算法项剥离开。
仍旧以上面的动物为例:
由于上面使用了两个行为(发声、移动),那么首先我们创建两个抽象行为类(发声、移动)
发声类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.sound;
/**
* 发声超类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public interface Sound {
public abstract void sound();
}
并有以下几个实现类。
咯咯叫的实现类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.sound;
/**
* 咯咯发声子类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public class GeGeSound implements Sound{
@Override
public void sound() {
System.out.println("咯咯咯咯.....");
}
}
不会叫的实现类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.sound;
/**
* 不会发声子类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public class NoSound implements Sound{
@Override
public void sound() {
System.out.println("我不会说话.....");
}
}
移动超类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.move;
/**
* 移动超类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public interface Move {
public abstract void move();
}
走着移动的子类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.move;
/**
* 两条腿走路子类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public class WalkMove implements Move{
@Override
public void move() {
System.out.println("两条腿走路...");
}
}
游泳移动的子类:package com.beBianMin.shareLogger.animal.strategyMode.behavior.move;
/**
* 游泳走路子类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
public class SwimMove implements Move{
@Override
public void move() {
System.out.println("游泳走路.....");
}
}
接下来就是动物的超类,在超类中可以引入所有的行为超类,同时这个超类中定义了一个不变的行为(是否有眼睛)package com.beBianMin.shareLogger.animal.strategyMode.behavior;
/**
* 动物超类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*
*/
import com.beBianMin.shareLogger.animal.strategyMode.behavior.move.Move;
import com.beBianMin.shareLogger.animal.strategyMode.behavior.sound.Sound;
public abstract class Animal {
Move move;//移动超类
Sound sound;//发声超类
public Animal() {
// TODO Auto-generated constructor stub
}
/**
* 发声方式
*/
void sound() {
sound.sound();
};
/**
* 移动方式
*/
void move() {
move.move();
}
void eye() {
System.out.println("我有眼睛....");
}
public Move getMove() {
return move;
}
public void setMove(Move move) {
this.move = move;
}
public Sound getSound() {
return sound;
}
public void setSound(Sound sound) {
this.sound = sound;
};
}
由于策略模式要讲行为算法逻辑和调用算法逻辑分开,因此在超类中就可以直接调用具体的行为超类的方法,实现行为算法和调用算法分离的目的。即上面代码中的如下代码:/**
* 发声方式
*/
void sound() {
sound.sound();
};
鸡的子类,有两个行为,声音、移动:package com.beBianMin.shareLogger.animal.strategyMode.behavior;
import com.beBianMin.shareLogger.animal.strategyMode.behavior.move.WalkMove;
import com.beBianMin.shareLogger.animal.strategyMode.behavior.sound.GeGeSound;
/**
* 鸡的实现类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*/
public class Chicken extends Animal{
public Chicken() {
move = new WalkMove();
sound = new GeGeSound();
}
}
在子类中是需要实例化行为对象即可(本利在构造函数中实例化)
鱼子类也有发声和移动两个行为。package com.beBianMin.shareLogger.animal.strategyMode.behavior;
import com.beBianMin.shareLogger.animal.strategyMode.behavior.move.SwimMove;
import com.beBianMin.shareLogger.animal.strategyMode.behavior.sound.NoSound;
/**
* 鱼的实现类
* @author 郭鹏飞
* @网址 https://wwww.bajson.com
*/
public class Fish extends Animal{
public Fish() {
move = new SwimMove();
sound = new NoSound();
}
}
测试类代码:package com.beBianMin.shareLogger.animal.strategyMode.behavior;
public class TestMain {
public static void main(String[] args) {
Animal chicken = new Chicken();
Animal fish = new Fish();
System.out.println("鸡的 行为-------------");
chicken.sound();
chicken.move();
chicken.eye();
System.out.println("鱼的 行为-------------");
fish.sound();
fish.move();
chicken.eye();
}
}
整个代码结构如下:
打印结果如下:鸡的 行为-------------
咯咯咯咯.....
两条腿走路...
我有眼睛....
鱼的 行为-------------
我不会说话.....
游泳走路.....
我有眼睛....
3、总结:
使用策略模式要注意几点:
1)要分析项目中的变与不变的部分,例如上面实例中不变部分为是否有眼睛的行为,而变的部分就是移动方式行为和发声行为
2)多用组合,少用继承;使用行为组的组合,而不是使用行为的继承,可以使项目更加灵活,复用性更强,组合性更好。
3)设计模式只是一种经验或者说是一种项目实现的方法方式,并没有对应的框架,是需要我们在实际开发中结合实际需求不断总结、摸索出的经验。值得注意的是,目前一些库或者框架本身就使用了某些设计模式。
4)基本上项目开发中都可以使用设计模式来实现,除非你开发的这个项目非常特殊。