首页 > 其他分享 >策略模式

策略模式

时间:2024-08-27 09:27:30浏览次数:6  
标签:Runnable run 策略 Thread 模式 接口 public

策略模式

​ 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改,我们创建表示各种策略的对象和运算规则随着策略对象的改变而改变。策略模式把对象本身和运算规则进行了分离。

一、使用场景

​ 我们知道 Java 中实现线程执行单元的方式另一种方式是实现 Runnable 接口,并重写其中的 run 方法,然后将对应的 Runnable 接口实现类作为 Thread 类构造方法的参数进行 Thread 的对象创建。这里其实就使用了策略模式。

Thread 部分源码:

public
class Thread implements Runnable {  
    ...
	/* What will be run. */
    private Runnable target;
    ...
        
    /**
     * Allocates a new {@code Thread} object. This constructor has the same
     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
     * {@code (null, target, gname)}, where {@code gname} is a newly generated
     * name. Automatically generated names are of the form
     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
     *
     * @param  target
     *         the object whose {@code run} method is invoked when this thread
     *         is started. If {@code null}, this classes {@code run} method does
     *         nothing.
     */
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
        
    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
}

我们可以看到 Thread 不仅实现类 Runnable 接口,同时还维护了一个 Runnable 属性,在重写的 run 方法中进行了一个判断,如果这个属性不为空我们就调用对应这个属性的 run 方法。

二、简单示例

​ 这里使用一个简单示例来演示,因为示例可以更侧重于对设计模式的体现,而实际使用场景不止需要考虑策略模式本身可能看着就有点疑惑。

首先我们定义一个策略接口

​ 对标 Runnable 接口中的 run 方法,对于 run 则是表示线程所需要执行的方法(可以理解为线程执行策略的一种抽象)

package strategypattern;

/**
 * 旅行策略接口
 */
public interface TravelStrategy {

    // 表示我们具体的旅行方式
    void travelAlgorithm ();
}
然后我们定义具体的策略

​ 这里就相当于你自己定义了类实现了 Runnable 接口并重写了 run 方法

package strategypattern;

/**
 * 表示坐汽车
 */
public class CarStrategy implements TravelStrategy{

    /**
     * 重写具体旅游策略
     */
    @Override
    public void travelAlgorithm() {
        System.out.println("坐汽车");
    }
}
package strategypattern;

/**
 * 表示坐高铁
 */
public class HighTrainStrategy implements TravelStrategy{

    /**
     * 重写具体旅游策略
     */
    @Override
    public void travelAlgorithm() {
        System.out.println("坐高铁");
    }
}
最后我们定义一个旅行者即使用这个策略的对象

​ 这个类就类似于 Thread 类

package strategypattern;

/**
 * 旅行者
 */
public class Traveler {

    /**
     * 首先在内部维护一个抽象策略接口对象
     */
    private TravelStrategy travelStrategy;

    public Traveler() { }

    /**
     * 这里我们使用构造方法给属性赋值,当然你也可以使用set方法
     * @param travelStrategy
     */
    public Traveler(TravelStrategy travelStrategy) {
        this.travelStrategy = travelStrategy;
    }

    /**
     * 这里我们旅行者的出行方式的方法
     */
    public void travelStyle () {
        travelStrategy.travelAlgorithm () ;
    }
}
测试
package strategypattern;

/**
 * @Package: strategypattern
 * @Author: yanjiali
 * @Created: 2024/8/26 22:04
 */
public class Main {
    public static void main(String[] args) {
        //比如我们想要使用汽车出行
        CarStrategy carStrategy = new CarStrategy();
        Traveler traveler = new Traveler(carStrategy);
        traveler.travelStyle();
    }
}

//对应输出:
坐汽车

三、总结

优点:
我们之前在选择出行方式的时候,往往会使用 if-else 语句,也就是用户不选择 A 那么就选择 B 这样的一种情况。这种情况耦合性太高了,而且代码臃肿,有了策略模式我们就可以避免这种现象;
策略模式遵循开闭原则,实现代码的解耦合。扩展新的方法时也比较方便,只需要继承策略接口就好了。

缺点:
客户端必须知道所有的策略类,并自行决定使用哪一个策略类;
策略模式会出现很多的策略类;
客户端在使用这些策略类的时候,这些策略类由于继承了策略接口,所以有些数据可能用不到,但是依然初始化了。

​ 简单来说,策略模式实现了具体策略和执行策略者的分离,使得我们在后续扩展时比直接写 if-else 要好,当新的具体策略需求到来时我们可以编写对应的策略实现类,而不需要对已有的代码进行修改。

标签:Runnable,run,策略,Thread,模式,接口,public
From: https://www.cnblogs.com/fragmentary/p/18381989

相关文章

  • 从主流技术架构视角剖析 Java Web 项目的性能测试策略与挑战
    随着互联网应用的不断发展,JavaWeb项目在企业级应用中占据了重要地位。然而,如何在复杂的技术架构下,确保项目的高性能和稳定性,成为了每个开发与测试团队无法回避的难题。今天,我们将从主流技术架构的视角,深度剖析JavaWeb项目的性能测试策略与面临的挑战,为你揭开性能优化的神......
  • 2.1 单例模式【面试重点】
    单例模式单例设计模式介绍所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象。SessionFa......
  • Spring MVC (什么是MVC ?MVC模式又是什么 ?SpringMVC 的执行流程)
    1、MVC是什么?1.1、MVCSpringMVC(全称SpringWebMVC)是Spring框架提供的一款基于MVC模式的轻量级Web开发框架,是Spring为表示层(UI)开发提供的一整套完备的解决方案。注:三层架构分为表示层(UI)、业务逻辑层(BLL)、数据访问层(DAL),表示层则包含前台页面和后台Servlet,Sprin......
  • C++ 设计模式——享元模式
    C++设计模式——享元模式C++设计模式——享元模式1.主要组成成分2.享元模式内部状态3.享元模式外部状态4.逐步构建享元模式4.1抽象享元类定义4.2具体享元类实现4.3享元工厂类实现4.4主函数5.享元模式UML图享元模式UML图解析6.享元模式的优点7.享元模......
  • 设计模式基础
    1.面向对象设计的原则(七大原则)1.1单一职责(SPR:SingleResponsibilitiesPrinciple):一个类应只负责一个功能领域的相关职责,即只有一个使它变化的原因1.2开放闭合(OCP:Open-ClosePrinciple):软件实体应对扩展开发,对修改关闭,即实体可以扩展,但不能在原来的实体上修改1.3里氏代换(LSP:......
  • 【AI大模型算法工程师就业指南】—— 高薪就业策略,转行大模型领域的诚挚建议!
    从ChatGPT到新近的GPT-4,GPT模型的发展表明,AI正在向着“类⼈化”⽅向迅速发展。GPT-4具备深度阅读和识图能⼒,能够出⾊地通过专业考试并完成复杂指令,向⼈类引以为傲的“创造⼒”发起挑战。现有的就业结构即将发⽣重⼤变化,社会⽣产⼒的快速提升将催⽣新的⾏业和岗位机会。如......
  • SparkSQL日期时间模式详解
    datatime使用场景CSV/JSON数据源使用模式字符串来解析和格式化日期时间内容。日期时间函数用于转换StringType类型到DateType或TimestampType类型,反之亦然。例如,unix_timestamp,date_format,to_unix_timestamp,from_unixtime,to_date,to_timestamp,from_utc_timestam......
  • SparkSQL数值模式详解
    简介函数如to_number和to_char确实支持在字符串类型和十进制(数值)类型之间进行转换。这些函数接受格式字符串作为参数,这些格式字符串指示了如何在这两种类型之间映射。to_number:这个函数通常用于将字符串转换成数值类型。你需要提供一个格式字符串来指定如何解释字符串......
  • Python批量发送邮件如何实现邮件群发策略?
    Python批量发送邮件怎么定制化?如何使用Python发信?Python批量发送邮件已经成为一种不可或缺的工具。Python批量发送邮件都能大大提高效率,节省时间和资源。AokSend将详细介绍如何利用Python批量发送邮件实现高效的邮件群发策略。Python批量发送邮件:设置环境要开始Python批量......
  • 设计模式2个黄鹂鸣翠柳-《分析模式》漫谈23
    DDD领域驱动设计批评文集做强化自测题获得“软件方法建模师”称号《软件方法》各章合集“AnalysisPatterns”的第一章有这么一句:The"GangofFour"bookhashadmuchmoreinfluenceinsoftwarepatternsthanAlexander'swork,and three outofthose four auth......