策略模式(java)

今天,看java编程思想9.3章学习到了策略模式,以前也学习过,总是忘,所以记录一下。
首先需要说明的是,设计模式只是编写低耦合,高内聚,扩展性好的一种实现方式,它是人们总结出来的经验,不是规定一定要这么做,但是设计模式都遵循六大原则,这是设计类的时候尽量要去遵守的,这样每个人都可以有自己的设计模式。
策略模式定义什么的就先不说了,直接来个实际问题比较容易理解

假设现在公司想让我开发一个排序算法库,然后公司的其他开发人员(客户端程序员)会调用这些算法,实现一些功能。 排序算法有如下:
1. 冒泡排序
2. 插入排序
3. 快速排序
4. 堆排序

那么我该怎么设计这个库,才能让 其他开发人员容易调用,然后我自己以后也容易再增加算法呢?

先不管了,完成任务了事(为了方便写在一个文件里了)

import java.lang.*;
import java.util.*;

class SortUtils{
    public int[] maopaoSort(int[] src){
        System.out.println("after maopao");
        return src;
    }
    public int[] charuSort(int[] src){
        System.out.println("after charu");
        return src;
    }
    public int[] kuaisuSort(int[] src){
        System.out.println("after kuaisu");
        return src;
    }
    public int[] duiSort(int[] src){
        System.out.println("after dui");
        return src;
    }
}
// Main 是客户端程序员需要建的
public class Main{
    public static void print(int[] res){
        for(int i=0; i<5; i++){
            System.out.print(res[i]+" ");
        }
        System.out.println("-------");
    }
    public static void main(String[] args){
        SortUtils su = new SortUtils();
        int[] src = {1,2,3,4,5};
        System.out.println("src");
        print(src);
        int[] res = su.maopaoSort(src);
        print(res);
        res = su.charuSort(src);
        print(res);
        res = su.kuaisuSort(src);
        print(res);
        res = su.duiSort(src);
        print(res);
    }
}

排序算法有很多种,有的速度比较快,有的占用的内存小,有的排序比较稳定,其他的开发人员可以自由的选择他想要的排序算法,上面的代码看起来可以正常的工作了(假装的),客户端程序要只需要调用su.xxxSort(int [] src),就可以使用了。但是如果我们想要增加一个排序算法比如基数排序,那就需要在这个文件中添加一个方法jishuSort(int[] src),这样就违反了开闭原则,即对修改关闭,对扩展开放。意思就是说如果随便修改原有的类的话容易引入错误,导致原有的功能出现问题,所以尽量去增加新的类去完成功能。所以我们可以把这些排序算法都设计成单独的类,而且这些类都具有相似的功能,我们可以设计一个抽象的父类,让具体的排序算法都继承父类去实现。然后用int[]也不好,相信客户端程序员一般都会用List<Integer>去保存原始数组,最后,新一代的代码出炉了。

import java.lang.*;
import java.util.*;

abstract class Sort{
    abstract public List<Integer> sort(List<Integer> src);
}

class MaopaoSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after maopao");
        return src;
    }
}
class CharuSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after charu");
        return src;
    }
}
class KuaisuSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after kuaisu");
        return src;
    }
}
class DuiSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after dui");
        return src;
    }
}
public class Main{
    public static void print(List<Integer> res){
        for(int i=0; i<5; i++){
            System.out.print(res.get(i)+" ");
        }
        System.out.println("-------");
    }
    public static void main(String[] args){
        List<Integer> src = new ArrayList<Integer>();
        src.add(1); src.add(2); src.add(3); src.add(4); src.add(5);
        Sort s = new MaopaoSort();
        List<Integer> res = s.sort(src);
        print(res);

        s = new CharuSort();
        res = s.sort(src);
        print(res);

        s = new KuaisuSort();
        res = s.sort(src);
        print(res);

        s = new DuiSort();
        res = s.sort(src);
        print(res);
    }
}

这样如果在增加一个基数排序的话,只需要编写一个继承Sort的类并实现sort方法就可以了。嗯。。还有一个地方需要完善一下,客户端程序员调用具体的排序算法时需要知道具体的方法sort,可不可以把这个sort隐藏一下,这样改名字什么的,客户端程序员就不需要变代码啦。那么再增加一个类,帮助客户端程序员去调用sort方法。可以这样写

import java.lang.*;
import java.util.*;

abstract class Sort{
    abstract public List<Integer> sort(List<Integer> src);
}

class MaopaoSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after maopao");
        return src;
    }
}
class CharuSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after charu");
        return src;
    }
}
class KuaisuSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after kuaisu");
        return src;
    }
}
class DuiSort extends Sort{
    public List<Integer> sort(List<Integer> src){
        System.out.println("after dui");
        return src;
    }
}
// 增加的
class Apply {
    private static void print(List<Integer> res){
        for(int i=0; i<5; i++){
            System.out.print(res.get(i)+" ");
        }
        System.out.println("-------");
    }
    public static List<Integer> sort(Sort s,List<Integer> src){
        List<Integer> res = s.sort(src);
        print(res);
        return res;
    }
}
public class Main{
    public static void main(String[] args){
        List<Integer> src = new ArrayList<Integer>();
        src.add(1); src.add(2); src.add(3); src.add(4); src.add(5);

        Apply.sort(new MaopaoSort(), src);
        Apply.sort(new CharuSort(), src);
        Apply.sort(new KuaisuSort(), src);
        Apply.sort(new DuiSort(), src);

    }
}

增加了Apply类,使用process就可以来完成排序算法啦,客户端程序调用起来就不需要知道排序算法内部是通过sort函数来实现的了,调用起来也很简单,并且可以在Apply中添加一些别的功能,比如这里把打印函数放在里面了,而且内部怎么变化,客户端程序员都不要去知道。

回头来看看 策略模式的定义

策略模式:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

图解:
这里写图片描述

这样就比较容易理解了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
策略模式是一种行为设计模式,它允许您在运行时更改对象的行为。在策略模式中,您可以定义不同的算法或策略,并将它们封装在单独的类中,以便在运行时根据需要选择其中之一。 在 Java 中实现策略模式,您可以创建一个接口来定义算法的抽象方法,并创建一些实现该接口的类来实现不同的算法。然后,您可以在需要使用算法的类中创建一个成员变量来保存该算法的引用,并在运行时将其设置为不同的实现类的实例。这样,您就可以根据需要更改对象的行为,而不必更改其代码。 以下是一个简单的 Java 代码示例,演示了如何使用策略模式: ```java // 定义策略接口 interface Strategy { void execute(); } // 定义具体策略类 class ConcreteStrategyA implements Strategy { public void execute() { System.out.println("执行策略 A"); } } class ConcreteStrategyB implements Strategy { public void execute() { System.out.println("执行策略 B"); } } // 定义上下文类 class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public void executeStrategy() { strategy.execute(); } public void setStrategy(Strategy strategy) { this.strategy = strategy; } } // 使用策略模式 public class StrategyPatternExample { public static void main(String[] args) { // 创建具体策略类的实例 Strategy strategyA = new ConcreteStrategyA(); Strategy strategyB = new ConcreteStrategyB(); // 创建上下文对象,并设置初始策略 Context context = new Context(strategyA); // 执行策略 A context.executeStrategy(); // 更改策略为 B context.setStrategy(strategyB); // 执行策略 B context.executeStrategy(); } } ``` 在上面的示例中,我们定义了一个 `Strategy` 接口和两个具体策略类 `ConcreteStrategyA` 和 `ConcreteStrategyB`。我们还定义了一个 `Context` 类,该类包含一个 `Strategy` 类型的成员变量,并在 `executeStrategy()` 方法中调用该策略的 `execute()` 方法。在 `main()` 方法中,我们创建了 `ConcreteStrategyA` 和 `ConcreteStrategyB` 的实例,并将其传递给 `Context` 对象。我们还使用 `setStrategy()` 方法更改了上下文对象的策略,并在每次更改后调用 `executeStrategy()` 方法来执行新的策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值