设计模式-策略模式

基本概念

什么是策略模式

     策略模式(Strategy),定义了一组算法,将每个算法都封装起来,通过调用同一个父类达到不同策略之间可以的互换。

使用案例

     打个通俗的比方,在商场中有打折,满减,返利等不同类型的优惠活动,我们把每一种优惠活动称之为策略。所谓的策略模式其实就是让客户更好的切换这些策略,而不影响整个项目。
     再举个开发中经常遇到的例子。在微服务中负载均衡算法有轮询和随机两种。我们是如何切换选择使用哪种模式呐?当然是通过配置文件切换不同的算法。这里就是使用了设计模式中的策略模式。开发人员在配置文件中配置相关算法的配置信息,当程序运行时,会去读取配置文件,然后选择使用哪一种算法,从而在上下文中创建该种模式。

代码示例

示例内容

在这里插入图片描述

思维结构

代码所需的类和接口

  1. 创建一个所有飞机类型(策略)的父类接口。
  2. 创建不同种类飞机的model(表示不同的策略的model),实现父类策略接口的方法。
  3. 创建一个环境类,用于调用和管理使用策略模式。
  4. 创建一个xml配置文件,用于输入选择策略的信息。
  5. 创建一个xml读取工具。
  6. 创建客户端,用于调用环境类。

策略模式对应的结构图

在这里插入图片描述

具体代码

  1. 创建一个所有飞机类型(策略)的父类接口。
public interface Plane {
    String VERTICAL_TAKE = "垂直起飞";
    String LONG_DISTANCE_TAKE = "长距离起飞";
    //飞行特征
    String SUBSONIC_FLY = "亚音速飞行";
    String SUPERSONIC_FLY = "超音速飞行";
    public String getPlaneInfo();
}

  1. 创建不同种类飞机的model(表示不同的策略的model),实现父类策略接口的方法。
/**
 * @program: airplane
 * @description: 鹞式战斗机
 * @author: lichunkai
 * @create: 2020-02-15 23:33
 **/
public class Harrier implements Plane {
    @Override
    public String getPlaneInfo() {
        String info = new StringBuilder("起飞特征:").append(Plane.VERTICAL_TAKE)
                .append(",")
                .append("飞行特征:").append(Plane.SUPERSONIC_FLY)
                .toString();
        return info;
    }
}

/**
 * @program: airplane
 * @description: 客机
 * @author: lichunkai
 * @create: 2020-02-15 23:33
 **/
public class AirPlane implements Plane {
    @Override
    public String getPlaneInfo() {
        String info = new StringBuilder("起飞特征:").append(Plane.LONG_DISTANCE_TAKE)
                .append(",")
                .append("飞行特征:").append(Plane.SUBSONIC_FLY)
                .toString();
        return info;
    }
}
/**
 * @program: airplane
 * @description: 歼击机
 * @author: lichunkai
 * @create: 2020-02-15 23:33
 **/
 
public class Fighter implements Plane {
    @Override
    public String getPlaneInfo() {
        String info = new StringBuilder("起飞特征:").append(Plane.LONG_DISTANCE_TAKE)
                .append(",")
                .append("飞行特征:").append(Plane.SUPERSONIC_FLY)
                .toString();
        return info;
    }
}

/**
 * @program: airplane
 * @description: 直升机
 * @author: lichunkai
 * @create: 2020-02-15 23:32
 **/
public class Helicopter implements Plane {
    @Override
    public String getPlaneInfo() {
        String info = new StringBuilder("起飞特征:").append(Plane.VERTICAL_TAKE)
                .append(",")
                .append("飞行特征:").append(Plane.SUBSONIC_FLY)
                .toString();
        return info;
    }
}

  1. 创建一个环境类,用于调用和管理使用策略模式。

/**
 * @program: airplane
 * @description: 特征类:环境类
 * @author: lichunkai
 * @create: 2020-02-15 23:15
 **/
public class TraitEnv {
    private Plane plane;

    public String getTraitInfo() {
        //省略实际开发中可能需要用到的共用代码
        if(null == plane){
            return "未获取到相关信息";
        }
        return plane.getPlaneInfo();
    }

    public void setPlane(Plane plane) {
        this.plane = plane;
    }

/*    public void setTraitInfo(String traitInfo) {
        this.traitInfo = traitInfo;
    }*/
}

  1. 创建一个xml配置文件,用于输入选择策略的信息。
<?xml version="1.0" encoding="GBK" ?>
<config>
<!--
    <Plane>strategy.lck.model.AirPlane</Plane>
    <Plane>strategy.lck.model.Fighter</Plane>
    <Plane>strategy.lck.model.Harrier</Plane>
    -->
<Plane>strategy.lck.model.Helicopter</Plane>
</config>

  1. 创建一个xml读取工具。

/**
 * xml工具类
 */
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import strategy.lck.model.Plane;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;

public class XMLUtil {
    //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
    public	static	Object	getBean(String className)	{
        try	{
            //创建文档对象
            DocumentBuilderFactory	dFactory	=	DocumentBuilderFactory.newInstance();
            DocumentBuilder	builder	=	dFactory.newDocumentBuilder();
            Document	doc;
            //doc	=	builder.parse(new	File("config.xml"));
            doc = builder.parse(new File(Plane.class.getResource("/config_strategy.xml").getPath()));

            //获取包含类名的文本节点
            NodeList	nl	=	doc.getElementsByTagName(className);
            Node	classNode = nl.item(0).getFirstChild();
            String	cName = classNode.getNodeValue();

            //通过类名生成实例对象并将其返回
            Class	c= Class.forName(cName);
            Object	obj = c.newInstance();
            return	obj;
        }
        catch(Exception	e)	{
            e.printStackTrace();
            return	null;
        }
    }
}

  1. 创建客户端,用于调用环境类。

/**
 * @program: airplane
 * @description:客户端
 * @author: lichunkai
 * @create: 2020-02-15 23:56
 **/
public class Client {
    public static void main(String[] args) {
        //直升机(Helicopter)
        //客机(AirPlane)
        //歼击机(Fighter)
        //鹞式战斗机(Harrier)
        TraitEnv traitEnv = new TraitEnv();
        Plane airPlane = (Plane) XMLUtil.getBean("Plane");
        traitEnv.setPlane(airPlane);
        System.out.println(traitEnv.getTraitInfo());
    }
}

运行结果如下
在这里插入图片描述

结论

策略模式的总结:

策略模式用户算法的自由切换和扩展,他是应用较为广泛的设计模式之一。策略模式对应解决某一问题的一个算法族,允许用户从该算法族中任选一个来解决某一问题,同时可以方便的更换或者增加新的算法。只要涉及到算法的封装、复用和切换都可以考虑使用策略模式。

主要优点:

1、对开闭原则的完美支持
2、复用性强
3、可以多中继承方式实现
4、避免多条件选择语句

主要缺点:

1、客户端必须知道所有的算法逻辑以及却别
2、产生很多的具体策略类
3、无法同时在客户端使用多个策略类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值