策略模式详解

策略模式详解

设计模式总则第一条:对修改关闭,对扩展开放

抄了些东西:https://blog.csdn.net/tugangkai/article/details/88074288

策略模式的优点:

1.策略模式的功能就是通过抽象、封装来定义一系列的算法,使得这些算法可以相互替换,所以为这些算法定义一个公共的接口,以约束这些算法的功能实现。如果这些算法具有公共的功能,可以将接口变为抽象类,将公共功能放到抽象父类里面。

2.策略模式的一系列算法是可以相互替换的、是平等的,写在一起就是if-else组织结构,如果算法实现里又有条件语句,就构成了多重条件语句,可以用策略模式,避免这样的多重条件语句。

3.扩展性更好:在策略模式中扩展策略实现非常的容易,只要新增一个策略实现类,然后在使用策略实现的地方,使用这个新的策略实现就好了。

策略模式的缺点:

1.客户端必须了解所有的策略,清楚它们的不同:

如果由客户端来决定使用何种算法,那客户端必须知道所有的策略,清楚各个策略的功能和不同,这样才能做出正确的选择,但是这暴露了策略的具体实现。

2.增加了对象的数量:

由于策略模式将每个具体的算法都单独封装为一个策略类,如果可选的策略有很多的话,那对象的数量也会很多。

3.只适合偏平的算法结构:

由于策略模式的各个策略实现是平等的关系(可相互替换),实际上就构成了一个扁平的算法结构。即一个策略接口下面有多个平等的策略实现(多个策略实现是兄弟关系),并且运行时只能有一个算法被使用。这就限制了算法的使用层级,且不能被嵌套。

策略模式的本质:

分离算法,选择实现。

如果你仔细思考策略模式的结构和功能的话,就会发现:如果没有上下文,策略模式就回到了最基本的接口和实现了,只要是面向接口编程,就能够享受到面向接口编程带来的好处,通过一个统一的策略接口来封装和分离各个具体的策略实现,无需关系具体的策略实现。

貌似没有上下文什么事,但是如果没有上下文的话,客户端就必须直接和具体的策略实现进行交互了,尤其是需要提供一些公共功能或者是存储一些状态的时候,会大大增加客户端使用的难度;引入上下文之后,这部分工作可以由上下文来完成,客户端只需要和上下文进行交互就可以了。这样可以让策略模式更具有整体性,客户端也更加的简单。

策略模式体现了开闭原则:策略模式把一系列的可变算法进行封装,从而定义了良好的程序结构,在出现新的算法的时候,可以很容易的将新的算法实现加入到已有的系统中,而已有的实现不需要修改。

策略模式体现了里氏替换原则:策略模式是一个扁平的结构,各个策略实现都是兄弟关系,实现了同一个接口或者继承了同一个抽象类。这样只要使用策略的客户端保持面向抽象编程,就可以动态的切换不同的策略实现以进行替换。

下图为 随身听播放 – 歌手曲库的模型

歌手类可以任意扩展,比如加入张学友,加入张韶涵
对歌手-- sing() --唱歌这件事进行了封闭,不准修改
在这里插入图片描述
下面是代码实现:

1.运行

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

        MyContext gemContext = new MyContext(new GEM());
        gemContext.start();



    }
}

2.上下文

/**
 * 策略模式的上下文
 *  赋值 -- 启动
 */

public class MyContext {
    private Singer singer;
    public MyContext(Singer singer) {
        this.singer = singer;
    }
    public void start(){
        singer.sing();
    }
}

3.固定不变的规则 ---- 接口

/**
 *  对扩展开放
 */

public interface Singer {
    void sing();
}

4.可以增加,删除的具体类

/**
 * 邓紫棋
 */
public class GEM implements Singer{
    @Override
    public void sing() {
        System.out.println("喜欢你");
        System.out.println("光年之外");
        System.out.println("泡沫");
    }
}
/**
 * 周杰伦  对修改关闭
 */

public class JZhou  implements Singer{
    @Override
    public void sing() {
        System.out.println("七里香");
        System.out.println("稻香");
        System.out.println("兰亭序");
    }
}
/**
 * 刘德华
 */

public class LiuDeHua implements Singer {
    @Override
    public void sing() {
        System.out.println("爱你一万年");
        System.out.println("坏小孩");
        System.out.println("开心马骝");
    }
}

Android中用到的例子:

ListView 的 ListAdapter 是接口,
ArrayAdapter是子类,
ListView是上下文

  • 如 setAdapter 里的 listAdapter.unregisterDataSetObserver(mDataSetObserver);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值