设计模式——策略模式

所有源码的git地址https://gitee.com/0x208_jackson/design-patterns

1、设计模式该怎么用

​ 当我们项目中出现了多个if……else的时候就可以选择使用策略模式,策略模式就是做同一件事件的不同的方法,设计模式说到底就是java多态的灵活运用。设计项目时我们一般要遵循开闭原则,即关闭修改,打开扩展,也就是说尽量别去修改现有的代码,而是对其进行扩展,这就要求我们在设计的时候需要考虑到可以进行灵活的扩展。

2、策略模式-比较动物大小

2.1、根据体重比较

我们现在有一只猫,根据体重比较猫的大小,代码如下:

猫的实体对象

package com.xin.demo.strategy;

import java.io.Serializable;

public class Cat implements Serializable {
    private final int weight;
    private final int height;

    public int compareToHeight(Cat cat) {
        return this.weight - cat.weight;
    }

    public Cat(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '}';
    }
}

排序:

package com.xin.demo.strategy;

public class Sort {
    // 此处通过 采用选择排序进行排序
    public static void selectionSort(Cat[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
              // 此处是重点需要注意,注意看调用的方法名
              // 此处需要根据 不同的比较方式去调用不同的方法,也就是会产生多个if……else
              minIndex = arr[j].compareToHeight(arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

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

}

执行:

package com.xin.demo.strategy;

import java.util.Arrays;

public class OperatorMain {
    public static void main(String[] args) {
        Cat[] a = {new Cat(23, 2),
                new Cat(14, 11),
                new Cat(5, 7),
                new Cat(1, 1)};
        Sort.selectionSort(a);
        System.out.println(Arrays.toString(a));
    }
}
2.2、根据身高比较

现在我希望根据猫的身高比较猫的大小,按照常规写法,我们需要在 Cat 对象里面在实现一个方法.

package com.xin.demo.strategy;

import java.io.Serializable;

public class Cat implements Serializable {
    private final int weight;
    private final int height;
  
    public int compareToHeight(Cat cat) {
        return this.weight - cat.weight;
    }

    // 此处为新增加的 根据体重进行比较的方法
    public int compareToWeight(Cat cat) {
        return this.weight - cat.weight;
    }

    public Cat(int weight, int height) {
        this.weight = weight;
        this.height = height;
    }

    @Override
    public String toString() {
        return "Cat{" +
                "weight=" + weight +
                ", height=" + height +
                '}';
    }
}

修改排序的调用方法

package com.xin.demo.strategy;

public class Sort {
    // 此处通过 采用选择排序进行排序
    public static void selectionSort(Cat[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
            // 注意此处改成了 调用体重的方法
            // 此处需要根据 不同的比较方式去调用不同的方法,也就是会产生多个if……else
 							minIndex = arr[j].compareToWeight(arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

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

}

2.3、根据策略模式

​ 以上两种情况我们发现,如果在做同一件猫的大小的比较,根据不同的方式去做的时候我们需要写很多冗余的代码,且不利于扩展,如在增加一种比较方式的时候,我们需要继续进行方法的迭代,且排序方法需要在增加或者重写,此处策略主要针对的是排序部分。

​ 既然是同一件事情,不同的方式去做,那么我们可以定义一个比较器接口,通过不同的实现来完成。

首先定义一个接口:

package com.xin.demo.strategy;

public interface Comparator<T> {

    // 比较器
    int compare(T o1, T o2);
}

对应的实现:

体重:

package com.xin.demo.strategy;

public class CatCompareToHeight implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        return o1.height - o2.height;
    }
}

身高:

package com.xin.demo.strategy;

public class CatCompareToWeight implements Comparator<Cat> {
    @Override
    public int compare(Cat o1, Cat o2) {
        return o1.weight - o2.weight;
    }
}

排序方法:

package com.xin.demo.strategy;

public class StrategySort<T> {
    // 此处通过 采用选择排序进行排序
    public void selectionSort(T[] arr, Comparator<T> comparator) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            int minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
              // 重点
                minIndex = comparator.compare(arr[j], arr[minIndex]) < 0 ? j : minIndex;
            }
            swap(arr, i, minIndex);
        }
    }

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

}

执行:

package com.xin.demo.strategy;

import java.util.Arrays;

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

        Cat[] cat = {new Cat(3, 4),
                new Cat(14, 11),
                new Cat(5, 17),
                new Cat(1, 2)};
        // 普通写法
        Sort.selectionSort(cat);
        System.out.println(Arrays.toString(cat));

        // 策略模式写法
        StrategySort<Cat> strategySort = new StrategySort<>();
        // 传进去需要比较的对象,以及对应的策略,也就是对应的比较方式
        // 根据身高比较
        strategySort.selectionSort(cat, new CatCompareToHeight());
        System.out.println("根据height排序:"+Arrays.toString(cat));

        //根据体重进行比较
        strategySort.selectionSort(cat, new CatCompareToWeight());
        System.out.println("根据weight排序:"+Arrays.toString(cat));

    }
}

2.4、可以比较任何动物的大小
package com.xin.demo.strategy;

import java.util.Arrays;

public class OperatorMain {
    public static void main(String[] args) {
        // 现在我们不仅可以比较猫的大小,还可以比较任何一个动物的大小
        // lambda 表达式写法
        StrategySort<Dog> dogStrategySort = new StrategySort<>();
        Dog[] dogs = {new Dog(3, 9),
                new Dog(1, 11),
                new Dog(4, 1),
                new Dog(2, 2)};
        dogStrategySort.selectionSort(dogs, new Comparator<Dog>() {
            @Override
            public int compare(Dog o1, Dog o2) {
                return o1.height - o2.height;
            }
        });
        System.out.println(Arrays.toString(dogs));
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在代码开发过程中,我们经常会遇到需要根据不同的条件执行不同的操作的情况。通常的做法是使用if-else语句来实现条件判断。但是,随着代码量的增加,if-else语句也会不断增多,代码变得越来越难以维护和扩展。为了解决这个问题,我们可以使用设计模式来重构代码,使其更加清晰、简洁和易于扩展。 状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变它的行为。状态模式将状态封装成独立的类,并将请求委托给当前的状态对象。当状态发生改变时,更改状态对象以及委托给它的请求处理。 下面我们以一个简单的电梯控制器为例,来演示如何使用状态模式来代替if-else语句。 首先,我们定义一个抽象的状态类: ```python class LiftState: def open(self): pass def close(self): pass def run(self): pass def stop(self): pass ``` 然后,我们定义具体的状态类,分别代表电梯处于打开、关闭、运行和停止状态: ```python class OpenState(LiftState): def open(self): print("电梯门已经打开了,不需要再打开了!") def close(self): print("电梯门关闭...") return CloseState() def run(self): print("电梯还没关门,不能上下楼!") def stop(self): print("电梯门已经打开了,不能停止!") class CloseState(LiftState): def open(self): print("电梯门打开...") return OpenState() def close(self): print("电梯门已经关闭了,不需要再关闭了!") def run(self): print("电梯开始运行...") return RunState() def stop(self): print("电梯已经停止了,不能再停止了!") class RunState(LiftState): def open(self): print("电梯正在运行,不能打开门!") def close(self): print("电梯正在运行,不能关闭门!") def run(self): print("电梯正在运行...") def stop(self): print("电梯停止运行...") return StopState() class StopState(LiftState): def open(self): print("电梯门打开...") return OpenState() def close(self): print("电梯已经停止了,不能关闭门!") def run(self): print("电梯开始运行...") return RunState() def stop(self): print("电梯已经停止了,不需要再停止了!") ``` 最后,我们定义一个电梯控制器类,用于控制电梯的状态: ```python class LiftController: def __init__(self): self.state = StopState() def set_state(self, state): self.state = state def open(self): self.state = self.state.open() def close(self): self.state = self.state.close() def run(self): self.state = self.state.run() def stop(self): self.state = self.state.stop() ``` 现在,我们可以通过调用电梯控制器类的方法来控制电梯的状态,而无需使用if-else语句: ```python lift_controller = LiftController() lift_controller.open() # 电梯门打开... lift_controller.close() # 电梯门关闭... lift_controller.run() # 电梯开始运行... lift_controller.stop() # 电梯停止运行... ``` 通过使用状态模式,我们可以将电梯控制器的不同状态封装成独立的类,使代码更加清晰、简洁和易于扩展。此外,状态模式还可以减少if-else语句的使用,提高代码的可读性和可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值