资讯专栏INFORMATION COLUMN

设计模式-策略模式

Freelander / 449人阅读

摘要:在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。换言之,策略模式只适用于客户端知道算法或行为的情况。策略模式概览图参考菜鸟教程策略模式十种常用的设计模式大部分自己总结,部分摘抄与模式之策略模式

策略模式

​ 我们都知道商场打折的时候,会根据会员的等级情况进行不同的折扣优惠,如果是VIP会员,那么可能就是5折优惠,如果是一般会员就是8折优惠,如果是普通顾客就是9折优惠,那么在结账的时候如何根据会员的等级进行不同的计算价格的方式呢?那么这个时候策略模式就派上用场了

定义

定义一组算法,将每个算法都封装起来,并且使他们之间可以互换。

动机

​ 在软件系统中,有许多算法可以实现某一功能,如查找、排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法;

​ 当然也可以将这些查找算法封装在一个统一的方法中,通过if…else…等条件判断语句来进行选择。

​ 这两种实现方法我们都可以称之为硬编码,如果需要增加一种新的查找算法,需要修改封装算法类的源代码;更换查找算法,也需要修改客户端调用代码。在这个算法类中封装了大量查找算法,该类代码将较复杂,维护较为困难。

结构

组件

Context:持有一个Strategy的引用。

抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。

具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。

实现

strategy类

package Strategy;

public interface Strategy {
    public void method1();

    public void method2();
}

具体策略

package Strategy;

public class ConcreteStrategy1 implements Strategy {
    @Override
    public void method1() {
        System.out.println("ConcreteStrategy1===算法1-version1");
    }

    @Override
    public void method2() {

        System.out.println("ConcreteStrategy1===算法2-version1");
    }
}
package Strategy;

public class ConcreteStrategy2 implements Strategy {
    @Override
    public void method1() {
        System.out.println("ConcreteStrategy2===算法1-version2");
    }

    @Override
    public void method2() {

        System.out.println("ConcreteStrategy2====算法2-version2");
    }
}

context

package Strategy;

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void method(){
        System.out.println("选择算法:" );
        strategy.method1();
        strategy.method2();

    }

}

client

package Strategy;

public class Client {
    public static void main(String[] args){

        Strategy concreteStrategy1 = new ConcreteStrategy1();
        Context context = new Context(concreteStrategy1);
        context.method();

        Strategy concreteStrategy2 = new ConcreteStrategy2();
        Context context1 = new Context(concreteStrategy2);
        context1.method();
    }
}
//选择算法:
//        ConcreteStrategy1===算法1-version1
//        ConcreteStrategy1===算法2-version1
//选择算法:
//        ConcreteStrategy2===算法1-version2
//        ConcreteStrategy2====算法2-version2
应用案例

如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为

一个系统需要动态地在几种算法中选择一种

如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

实际应用案例:旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略

strategy

package Strategy;

public interface Strategy {
    public void travel();

}

ConcreteStrategy1

package Strategy;

public class ConcreteStrategy1 implements Strategy {

    @Override
    public void travel() {
        System.out.println("坐飞机");
    }
}

ConcreteStrategy2

package Strategy;

public class ConcreteStrategy2 implements Strategy {
    @Override
    public void travel() {
        System.out.println("坐火车");
    }
}

context

package Strategy;

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void method(){
        System.out.println("选择出行方式:" );
        strategy.travel();

    }

}

client

package Strategy;

public class Client {
    public static void main(String[] args){

        Strategy concreteStrategy1 = new ConcreteStrategy1();
        Context context = new Context(concreteStrategy1);
        context.method();

        Strategy concreteStrategy2 = new ConcreteStrategy2();
        Context context1 = new Context(concreteStrategy2);
        context1.method();
    }
}
//选择出行方式:
//        坐飞机
//选择出行方式:
//        坐火车
优点

继承方面看(strategy-concreteStrategy)

可以灵活地增加新的算法或行为,只需要重新定义一个concretestrategy并实现strategy接口就行了

提供了管理相关的算法族的办法,使得所有的相似的算法都继承一个接口进行管理

避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后

保证了各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。

从用户的角度来看

不修改原有系统的基础上选择算法或行为,将选择算法的权力交给用户,用户想要哪种算法就实例化哪种

缺点

继承方面看

如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

用户角度看

客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。

策略模式概览图

参考

菜鸟教程

5. 策略模式

十种常用的设计模式(大部分自己总结,部分摘抄)

《JAVA与模式》之策略模式

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74937.html

相关文章

  • Java设计模式-策略模式

    摘要:可以使用其他模式来修正这个缺陷,如工厂方法模式代理模式或享元模式。我们的策略模式只是实现了策略的管理,但是没有严格地定义适当的场景使用适当的策略,在实际项目中,一般通过工厂方法模式来实现策略类的声明。源码地址参考文献设计模式之禅 定义 Define a family of algorithms,encapsulate each one,and make them interchange...

    dabai 评论0 收藏0
  • 设计模式策略模式

    摘要:一定义定义维基百科策略模式作爲一種軟件設計模式,指對象有某個行爲,但是在不同的場景中,該行爲有不同的實現算法。二策略模式图我们看看策略模式是有怎样设计结构的。如中创建线程池,线程池任务满时,对提交的任务做处理就使用了策略模式。以前完整的看过《大话设计模式》,虽然完整看过,也做过笔记,但现在依然很多已经很模糊。这段时间趁着离职,有时间,打算重新过一遍,该篇将介绍策略模式。一、定义定义(维基百科...

    番茄西红柿 评论0 收藏0
  • 设计模式策略模式

    摘要:一定义定义维基百科策略模式作爲一種軟件設計模式,指對象有某個行爲,但是在不同的場景中,該行爲有不同的實現算法。二策略模式图我们看看策略模式是有怎样设计结构的。如中创建线程池,线程池任务满时,对提交的任务做处理就使用了策略模式。以前完整的看过《大话设计模式》,虽然完整看过,也做过笔记,但现在依然很多已经很模糊。这段时间趁着离职,有时间,打算重新过一遍,该篇将介绍策略模式。一、定义定义(维基百科...

    番茄西红柿 评论0 收藏0
  • 设计模式策略模式

    摘要:一定义定义维基百科策略模式作爲一種軟件設計模式,指對象有某個行爲,但是在不同的場景中,該行爲有不同的實現算法。二策略模式图我们看看策略模式是有怎样设计结构的。如中创建线程池,线程池任务满时,对提交的任务做处理就使用了策略模式。以前完整的看过《大话设计模式》,虽然完整看过,也做过笔记,但现在依然很多已经很模糊。这段时间趁着离职,有时间,打算重新过一遍,该篇将介绍策略模式。一、定义定义(维基百科...

    MangoGoing 评论0 收藏0
  • 我的Java设计模式-策略模式

    摘要:孙膑心里一万个草泥马在奔腾,差点没噎死自己滚一边去,我们这盘跟他赛马开始,策略模式上场。在设计模式之禅中的提出通过策略枚举和反射机制对策略模式进行改良,膜拜了但是要添加或淘汰策略,还是得去对枚举进行修改,也不符合开闭原则。 今天给大家说说田忌赛马的故事。如有雷同,纯属巧合!话说在战国时期,群雄割据,硝烟四起,茶余饭后还是少不了娱乐活动的,其中赛马是最火爆的。一天,孙膑看到田忌像个死鸡似...

    zilu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<