策略设计模式

文章介绍了策略设计模式的概念,通过面对不同情况选择不同策略的例子进行解释。接着展示了UML类图,解释了策略(Strategy)、具体策略(ConcreteStrategy)和上下文(Context)的角色。文章通过Java代码示例,以学校运动会啦啦队表演为场景,演示了如何运用策略模式实现不同团队的表演策略,并讨论了如何使用枚举优化策略选择。最后,文章总结了策略模式的核心价值并邀请读者指正错误。
摘要由CSDN通过智能技术生成



一、策略设计模式

一般谈到策略,经常会讲面对某某情况我们需要采取什么样的策略应对,从这里就引出了策略设计模式的思想轮廓,即面对同一种事务在不同情况下需要采取不同的策略。比如约了女网友见面这一件事,需要考虑的情况有很多,如果她非常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组
四、总结

能力有限,纰漏之处,还望指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值