设计模式(3)-策略模式(Stragety)

前两篇分别讲了Dynamic Proxy(动态代理模式)和Iterator(迭代器模式),这次笔者来分享Stragety(策略模式)的小小经验。
笔者的设计模式经验是基于Object-Orient Programming(OOP)的,这三篇的blog基本的核心是多态代码的复用,要服用的目的是避免代码的写死,增加代码的Extensibility(拓展性),而拓展性的基础就是多态。笔者这里的多态基本是属于使用接口实现的,如果说继承中有名句“父类的引用指向子类的对象”,那么在接口实现中就是“接口的引用指向实现类的对象”(此仅为笔者个人的说法)。之所以不经常使用Inheritance(继承)的原因笔者在Dynamic Proxy中就算是说的比较清楚了,就是为了解耦
现在进入正题,为什么要称这次的设计模式为策略模式呢?依照笔者现在的经验来说就是说由于潜在的可选择方案多,每一种方案可能会导致一致的结果产生也可能导致不同的结果,故此我们需要选择哪种方案去实现就称为策略,譬如:Java中的Comparable & Comparator就是一种策略模式的具体实现例子,而今天笔者就是对这两个接口进行自定义的实现。

1.Question

在我们进行排序的时候,一般我们所最常接触到的排序策略有:冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序和堆排序,笔者学来一句谐音助记:冒择路兮快归堆(大意大概为:冒失地选择道路你离入坟不远了(>﹏<)).
现在,笔者想问一个问题:我们常使用这些排序的地方是不是就是单纯地排整型和浮点型数据?如果笔者问:咱们要对对象排序咋办?
内心独白估计是:。。。。。。尴尬!
对于我们不是计算机专业的更没有经过ACM训练的战五渣来说,算法的应用估计是没什么思路和想法的,请容许笔者说句后悔点的话:当初应该转数信的〒▽〒!跑去ACM打酱油也好啊!
有遗憾才证明自己是活着的(虽然我很不情愿地说这句话)。
回归正题,其实对于对象的排序也可以是通过整型和浮点型数据的排序,因为OO的思维是把它们封装成了属性,排序时上面的排序方式都都是可用的而且还是通过我们熟悉的简单排序的方式实习呢!然而,事情也不会简单到这么快让各位一下子看透了(多数人的思维是盲人摸象般的,很儿戏好吗!)
下面笔者将开始我们多版本的代码迭代来感受下Stragety,有些东西只可意会不可言传(其实是笔者没那个水平一下子将的清楚<-前面这句话其实是骗你的,基于一点:记住一个具体的实例从中提取信息比单纯的说概念要更易于接收,概念的东西是抽象的,抽象的东西实质就是不好好说人话)。

2.Example of data sort(code version1.0)

我们先是来下经典的冒泡排序。

DataSort.java

public class DataSort{
    public static void sort(int[] arr){
        for(int i = arr.length; i >= 0; i--){//外层控制大循环
            for(int j = 0; j < i - 1; j++){//内层控制小循环和交换
                if(a[j] > a[j + 1])
                    swap(a, j, j + 1);
            }
        }
    }

    public static void swap(int[] arr, int i, int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    public static void print(int[] arr){
        for(int i = 0; i < arr.length; i++){
            System.out.print(arr[i] + " "); 
        }
        System.out.println();
    }
}

Test.java

public class Test{
    public static void main(String[] args){
        int[] arr = new int[]{1, 11, 8, 22, 66};
        DataSort.sort(arr);
        DataSort.print(arr);
    }
}

这里写图片描述
如果我们这里需要对浮点型的数据排序,只要重载下以上方法就可以了(重载:同一个类中的方法,其方法同名,参数列表不同,记重载参数列表;重写/覆盖:重写父类中方法的实现,属于两个类间的关系)。

DataSort.java ver1.1

public class DataSort {

    public static void sort(int[] arr) {
        for (int i = arr.length; i >= 0; i--) {
            for (int j = 0; j < i - 1; j++) {
                if(arr[j] > arr[j + 1])
                    swap(arr, j, j + 1);
            }
        }
    }

    private static void swap(int[] arr, int j, int i) {
        int tmp = arr[j];
        arr[j] = arr[i];
        arr[i] = tmp;
    }


    public static void print(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }

    public static void sort(double[] arr) {
        for (int i = arr.length; i >= 0; i--) {
            for (int j = 0; j < i - 1; j++) {
                if(arr[j] > arr[j + 1])
                    swap(arr, j, j + 1);
            }
        }
    }

    private static void swap(double[] arr, int j, int i) {
        double tmp = arr[j];
        arr[j] = arr[i];
        arr[i] = tmp;
    }


    public static void print(double[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

3.Single object sort(code version1.1)

对单个类的排序我们其实不需要实现接口,以最简单的方法就可以完成。

Goods.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition 商品类
 * @created 2018-04-30-23:52
 */

public class Goods implements Comparable{
   private double price;
   private int weight;

    public Goods(double price, int weight) {
        this.price = price;
        this.weight = weight;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "¥:" + this.getPrice() + "|" + this.getWeight() + "kg";
    }
}

ObjDataSort.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition
 * @created 2018-04-30-23:56
 */

public class ObjDataSort {

    public static void sort(Goods[] obj) {//这里写死了只对Goods一类的支持
        for (int i = obj.length; i >= 0; i--) {
            for (int j = 0; j < i - 1; j++) {
                if(obj[j].getPrice() > obj[j + 1].getPrice())
                    swap(obj, j, j + 1);
            }
        }
    }

    private static void swap(Object[] obj, int j, int i) {
        Object tmp = obj[j];
        obj[j] = obj[i];
        obj[i] = tmp;
    }

    public static void print(Object[] obj) {
        for (int i = 0; i < obj.length; i++) {
            System.out.print(obj[i] + " ");
        }
        System.out.println();
    }
}

Test.java

public class Test{
    public static void main(String[] args){
        Goods[] goods = new Goods[]{new Goods(15.2, 15), new Goods(11.1, 11), new Goods(25.8, 25)};
        ObjDataSort.sort(goods);
        ObjDataSort.print(goods);
    }
}

这里写图片描述

4.Optimize the codes(code version1.2)

要优化其实就是说要可拓展,让代码复用,要复用一定会有多态。我们先得看得出哪一个地方写死了,再使用多态解决它。
很明显上面的sort中只支持Goods类型,这样可定是不行的,一旦要求改成飞机,汽车了就尴尬了,所以我们肯定要想一个它们中共同的特点来满足能够比较的特点,具体的实现交给它们自己实现。
基于这点思考,笔者做了以下优化。

Comparable.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition 可比较的接口
 * @created 2018-05-01-0:03
 */
public interface Comparable {
    int compareTo(Object o) throws Exception;
}

Goods.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition 商品类
 * @created 2018-04-30-23:52
 */

public class Goods implements Comparable{
   private double price;
   private int weight;

    public Goods(double price, int weight) {
        this.price = price;
        this.weight = weight;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "¥:" + this.getPrice() + "|" + this.getWeight() + "kg";
    }

    @Override
    public int compareTo(Object o) throws Exception {
        if(o instanceof Goods){
            Goods g1 = (Goods)o;
            return this.getPrice() > g1.getPrice() ? 1 : this.getPrice() < g1.getPrice() ? -1 : 0;
        }
        else
            throw new Exception("unable to compare " + o.getClass() + " to Goods");
    }
}

ObjDataSort.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition
 * @created 2018-04-30-23:56
 */

public class ObjDataSort {

    public static void sort(Comparable[] obj) {
        for (int i = obj.length; i >= 0; i--) {
            for (int j = 0; j < i - 1; j++) {
                try {
                    if(1 == obj[j].compareTo(obj[j + 1]))
                        swap(obj, j, j + 1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void swap(Comparable[] obj, int j, int i) {
        Comparable tmp = obj[j];
        obj[j] = obj[i];
        obj[i] = tmp;
    }

    public static void print(Comparable[] obj) {
        for (int i = 0; i < obj.length; i++) {
            System.out.print(obj[i] + " ");
        }
        System.out.println();
    }
}

这样各自的类都可进行自己本类对象间的比较,但是我么还是可以看到这还是不完善的,因为这个类里还有其他属性是可以支持比较,也就是还有其他潜在的策略没有支持到,笔者接下来接着改进。

5.Alternative Stragety(code version1.3)

为了避免compareTo的写死,我们是不是应该把比较的具体逻辑交给外面实现,然后再用compareTo调用这个实现,这样由于外部的实现是多种的,我们通过接口规范就实现复用了。

Comparator.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition 比较器接口
 * @created 2018-05-01-8:39
 */
public interface Comparator {
    int compare(Object o1, Object o2) throws Exception;
}

Goods.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition 商品类
 * @created 2018-04-30-23:52
 */

public class Goods implements Comparable{
   private double price;
   private int weight;

    public Goods(double price, int weight) {
        this.price = price;
        this.weight = weight;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    @Override
    public String toString() {
        return "¥:" + this.getPrice() + "|" + this.getWeight() + "kg";
    }

    @Override
    public int compareTo(final Object o) throws Exception {
        if(o instanceof Goods){
            Goods g1 = (Goods)o;
            Comparator c = new Comparator(){//这是为了偷懒不写一个完整的类

                @Override
                public int compare(Object o1, Object o2) throws Exception {
                    if(o1 instanceof Goods && o2 instanceof Goods){
                        return ((Goods) o1).getWeight() > ((Goods) o2).getWeight() ? 1 : ((Goods) o1).getWeight() < ((Goods) o2).getWeight() ? -1 : 0;
                    } else
                        throw new Exception("unable to compare " + o.getClass() + " to Goods");
                }
            };
            return c.compare(this, g1);
        }
        else
            throw new Exception("unable to compare " + o.getClass() + " to Goods");
    }
}

ObjDataSort.java

package com.unicorn.strategy;

/**
 * @author Unicorn
 * @descrition
 * @created 2018-04-30-23:56
 */

public class ObjDataSort {

    public static void sort(Comparable[] obj) {
        for (int i = obj.length; i >= 0; i--) {
            for (int j = 0; j < i - 1; j++) {
                try {
                    if(1 == obj[j].compareTo(obj[j + 1]))
                        swap(obj, j, j + 1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void swap(Comparable[] obj, int j, int i) {
        Comparable tmp = obj[j];
        obj[j] = obj[i];
        obj[i] = tmp;
    }

    public static void print(Comparable[] obj) {
        for (int i = 0; i < obj.length; i++) {
            System.out.print(obj[i] + " ");
        }
        System.out.println();
    }
}

这里写图片描述
这里三步过后就是完全做到比较策略的自主选择了,这就是策略模式了。
简单说说为什么实现了Comparable还要实现Comparator,尽管Comparable也可以做到比较策略的选择,但是每次都需要更改CompareTo的逻辑,这完全比不上我每次更换一个接口实现来的容易,也就是更改原有的实现,不如替换不同的实现;再者,这是一种组件的实现思维,组建之间各自的实现越细分越好,Iterator的Collection接口和Iterator接口也是这样的。
笔者这次就i到此为止了!
感谢各位的支持!
如果note有错漏,恳请各位留下评论指出,笔者会及时改正!
谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的体育馆管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本体育馆管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此体育馆管理系统利用当下成熟完善的SpringBoot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了用户在线选择试题并完成答题,在线查看考核分数。管理员管理收货地址管理、购物车管理、场地管理、场地订单管理、字典管理、赛事管理、赛事收藏管理、赛事评价管理、赛事订单管理、商品管理、商品收藏管理、商品评价管理、商品订单管理、用户管理、管理员管理等功能。体育馆管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:体育馆管理系统;SpringBoot框架;Mysql;自动化
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值