一、策略设计模式
一般谈到策略,经常会讲面对某某情况我们需要采取什么样的策略应对,从这里就引出了策略设计模式的思想轮廓,即面对同一种事务在不同情况下需要采取不同的策略。比如约了女网友见面这一件事,需要考虑的情况有很多,如果她非常nice,你可能需要认真收拾一下自己,如果一般般,那可能随便搞一搞就行了,如果根本没见过面,那最好是出门带个墨镜更合适。现实世界如此,编程亦是如此,比如商家的各种打折促销活动,不同等级vip用户的权限,只要是目标相同,不同情况下处理的方式不一样都可以使用看做是一种策略模式
二、UML图
- Strategy(策略):定义一个抽象接口;
- ConcreteStrategy(具体策略):实现接口具体的策略,换句话说就是描述每一个具体的策略
- Context(上下文):负责使用Strategy角色,保存ConcreteStrategy的实例,去实现需求。
三、示例
某学校举办为期一周的运动会,要求啦啦队每天都要出一个节目来给运动员们打气加油,比如第一天唱,第二天跳,第三天Rap…于是就找到了学校的艺术社,艺术社根据节目的不同,安排了不同的组,然后每一天由不同的组去表演节目,由于每一天的组不同,那自然表演节目也就不同了。
首先抽象一个顶层的接口
/**
* @author twotiger2tigersofast
* @description: 艺术团抽象
*/
public interface ArtCommunity {
/**
* @description: 表演
* @version 1.0
*/
void show();
}
不同团体的实现
/**
* @author twotiger2tigersofast
* @description: 唱组
*/
public class SingCommunity implements ArtCommunity {
/**团体名称*/
private String communityName;
/**表演时长*/
private Long time;
public SingCommunity(String communityName, Long time){
this.time = time;
this.communityName = communityName;
}
@Override
public void show() {
System.out.println("Show Sing for " + time + " minutes by " + communityName);
}
}
/**
* @author twotiger2tigersofast
* @description: 跳组
*/
public class JumpCommunity implements ArtCommunity {
/**团体名称*/
private String communityName;
/**表演时长*/
private Long time;
public JumpCommunity(String communityName, Long time){
this.time = time;
this.communityName = communityName;
}
@Override
public void show() {
System.out.println("Show Jump for " + time + " minutes by " + communityName);
}
}
/**
* @author twotiger2tigersofast
* @description: Rap组
*/
public class RapCommunity implements ArtCommunity {
/**团体名称*/
private String communityName;
/**表演时长*/
private Long time;
public RapCommunity(String communityName, Long time){
this.time = time;
this.communityName = communityName;
}
@Override
public void show() {
System.out.println("Show Rap for " + time + " minutes by " + communityName);
}
}
演员小组就位了,搭个舞台供他们来表演
/**
* author twotiger2tigersofast
* @description: 舞台(Context)
*/
public class StageContext {
private ArtCommunity act;
public StageContext(ArtCommunity act){
this.act =act;
}
/**
* @description: 开始演出
* @version 1.0
*/
public void startShow(){
act.show();
}
}
测试
public class TestStrategy {
public static void main(String[] args) {
//这里模拟第几天
int day = 2;
StageContext context = null;
if (day == 1){
context = new StageContext(new SingCommunity("Sing组", 5L));
} else if (day == 2){
context = new StageContext(new JumpCommunity("Jump组", 5L));
} else if (day == 3) {
context = new StageContext(new RapCommunity("Rap组", 5L));
} else if (day == 4) {
//sth else
}
context.startShow();
}
}
input:
Show Jump for 5 minutes by Jump组
假设校男篮认为篮球很有艺术成分,也加入了艺术团,这个时候篮球队想在第四天表演,那就按照艺术社的标准组建一个新的组,把他们在第四天的时候扔到舞台上去(只要他们遵循艺术团的标准,他们就能表演)
/**
* author twotiger2tigersofast
* @description: Basketball组
*/
public class BasketballCommunity implements ArtCommunity {
/**团体名称*/
private String communityName;
/**表演时长*/
private Long time;
public BasketballCommunity(String communityName, Long time){
this.time = time;
this.communityName = communityName;
}
@Override
public void show() {
System.out.println("Show Basketball for " + time + " minutes by " + communityName);
}
}
public class TestStrategy {
public static void main(String[] args) {
//这里模拟第几天
int day = 4;
StageContext context = null;
if (day == 1){
context = new StageContext(new SingCommunity("Sing组", 5L));
} else if (day == 2){
context = new StageContext(new JumpCommunity("Jump组", 5L));
} else if (day == 3) {
context = new StageContext(new RapCommunity("Rap组", 5L));
} else if (day == 4) {
context = new StageContext(new BasketballCommunity("Basketball组",5L));
}
context.startShow();
}
}
input:
Show Basketball for 5 minutes by Basketball组
通过这个简单例子,可以看出,本质上就是利用了多态的特性,不同情况传入不同对象,由context作为协调者,完成最终的行为
以上的代码有一大堆的if else ,强迫症患者可以利用枚举策略将其优雅的去掉,首先创建一个枚举:
public enum CommunityEnum {
SING(1,new SingCommunity("Sing组", 5L)),
JUMP(2,new JumpCommunity("Jump组", 5L)),
RAP(3,new RapCommunity("Rap组", 5L)),
BASKETBALL(4,new BasketballCommunity("Basketball组",5L));
private ArtCommunity act;
private int day;
CommunityEnum(int day,ArtCommunity act){
this.day = day;
this.act = act;
}
public static CommunityEnum match(int day){
Optional<CommunityEnum> communityEnum =
Arrays.stream(CommunityEnum.values()).filter(e -> e.getDay() == day).findFirst();
return communityEnum.isPresent() ? communityEnum.get() : null;
}
public ArtCommunity getAct() {
return act;
}
public void setAct(ArtCommunity act) {
this.act = act;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
}
将所有的策略对象用枚举表示,并对外提供一个match方法,根据day匹配具体的实例,在外部调用即可,
public class TestStrategy {
public static void main(String[] args) {
int day = 4;
CommunityEnum communityEnum = CommunityEnum.match(day);
Optional.ofNullable(communityEnum).ifPresent(e -> e.getAct().show());
}
}
input:
Show Basketball for 5 minutes by Basketball组
四、总结
能力有限,纰漏之处,还望指正~