问题是最好的老师
关于策略模式,他的业务需求是什么样的场景?
当然策略模式的实现不仅仅是策略模式,他和简单工厂的设计模式有什么样的关系?
试想一下,如果把简单工厂换成工厂,方法又会发生怎样的变化? 反射又如何应用?
策略模式是如何一步一步衍化的?是依据什么样的思路进行衍化的,衍化的每一次升级发生了哪些巨大的变化?
在策略模式中所有的 Uml图是如何对应代码的?
通过对策略模式的整体学习,结构化分析以及相关的深入,你用一句话来描述一下策略模式是如何以一步一步演化到现在的需求,并展示一下未来的策略模式将会是什么样子? 通过对策略模式的整体性思考,我们来分析一下我们的智慧,是怎么样一步一步解决这些问题的,并且能够很自然的进行演化。 去思考一个 N+1的成长过程?描绘一下策略模式的n+1的每一步轨迹, N+1能够演变的内在动力是什么?
举个例子,商场中的收费模式分为:正常收费,打折,满减。可以使用策略模式实现。(这是我最开始的理解)
后来变成了类似方法的理解,入参只有一个入口,出参也只有一个出口。
也就是说我们要算钱的话,不管是按照哪种策略算钱,都是入参都是原价,出参都是最终付钱的价格。基于这样的业务条件,使用策略模式。
策略模式(Strategy Pattern)是一种行为型设计模式,它允许在运行时选择算法的不同实现,并将其封装在独立的策略类中。这样可以使得算法的变化独立于使用它们的客户端。策略模式通过定义一系列算法,然后将其封装在各自的类中,使得这些算法可以相互替换,以满足不同的需求,同时不影响客户端的代码。
策略模式的主要参与者包括:
Context(上下文):上下文是客户端与策略之间的桥梁。它持有一个策略对象的引用,并在运行时切换不同的策略。上下文根据不同的情况或条件选择适当的策略进行调用。
Strategy(策略):策略是一个接口或抽象类,它定义了一组算法接口,各个具体策略类都实现这个接口。每个策略类封装了一种特定的算法。
使用策略模式的优点包括:
可扩展性:可以方便地增加新的策略类,扩展系统的功能,无需修改现有代码。
可维护性:由于不同的算法被封装在独立的策略类中,代码更加清晰和可维护。
代码复用:不同的上下文可以共享同一个策略,提高代码复用性。
策略模式只有和简单工厂或者工厂方法结合才有意义,因为context类中才是具体各个子类之间产生关系的地方,而策略模式最重要的点就是Context类中让各个子类有逻辑关系,二者缺一不可。
策略模式使用反射,带上配置文件
public class Client {
public static void main(String[] args) throws Exception {
Notice notice = new Notice();
notice.notice();
}
}
package com.example.designer20230731.Strategy1;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
public class Notice {
class GetParam {
private List<String> getParam() throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入算钱的方式,");
String wayOfSum = scanner.nextLine();
System.out.println("请输入总钱数");
String sumOfMoney = scanner.nextLine();
List<String> paramList = new ArrayList<>();
paramList.add(wayOfSum);
paramList.add(sumOfMoney);
return paramList;
}
}
public class ConfigUtil {
public String get(String key) throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream("E:\\zy\\TGB-zgy-2022\\MiMust\\MiDesignDemo\\JAVAtest\\Designer20230731\\src\\main\\resources\\application.properties"));
return properties.getProperty(key);
}
}
private void compositeBusiness() throws Exception {
while (true)
{
GetParam getParam = new GetParam();
List<String> param = getParam.getParam();
ConfigUtil configUtil = new ConfigUtil();
String Way = String.valueOf(configUtil.get(param.get(0)));
Context context = new Context(Way);
Double aDouble = Double.valueOf((param.get(1)));
context.contextInterface(aDouble);
}
}
public void notice() throws Exception {
this.compositeBusiness();
}
}
package com.example.designer20230731.Strategy1;
public class Context {
// Strategy strategy;
//
// public Context( Strategy strategy) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//
// this.strategy = strategy;
// }
//
//
// public void contextInterface(double money){
// strategy.acceptCash(money);
// }
Strategy strategy;
public Context( String Way) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> wayClass = Class.forName(Way);
Object instance = wayClass.newInstance();
IFactory factory = (IFactory) instance;
Strategy strategy1 = factory.createStrategy();
this.strategy = strategy1;
}
public void contextInterface(double money){
strategy.acceptCash(money);
}
}
public interface IFactory {
Strategy createStrategy();
}
public class NormalFactory implements IFactory{
public Strategy createStrategy() {
return new CashNormal();
}
}
public class RebateFactory implements IFactory{
public Strategy createStrategy() {
return new CashRebate(0.8);
}
}
public class RebateFactory implements IFactory{
public Strategy createStrategy() {
return new CashRebate(0.8);
}
}
public class ReturnFactory implements IFactory{
public Strategy createStrategy() {
return new CashReturn(300,10);
}
}
public abstract class Strategy {
public double acceptCash(double money) {
return 0;
}
}
public class CashNormal extends Strategy {
public double acceptCash( double money) {
System.out.println(money);
return money;
}
}
package com.example.designer20230731.Strategy1;
public class CashRebate extends Strategy {
double moneyRebate = 0.8;
public CashRebate(double moneyRebate){
this.moneyRebate = moneyRebate;
}
public double acceptCash( double money) {
System.out.println(money*moneyRebate);
return money*moneyRebate;
}
}
package com.example.designer20230731.Strategy1;
public class CashReturn extends Strategy {
private double moneyCondition = 0.00;
private double getMoneyReturn = 0.00;
public CashReturn(double moneyCondition, double getMoneyReturn) {
this.getMoneyReturn = getMoneyReturn;
this.moneyCondition = moneyCondition;
}
public double acceptCash(double money) {
double result = money;
// double init = money;
if (money > moneyCondition) {
result = money - getMoneyReturn;
System.out.println(result);
return result;
}
System.out.println(result);
return result;
}
}
配置文件
CashNormal=com.example.designer20230731.Strategy1.NormalFactory
CashRebate=com.example.designer20230731.Strategy1.RebateFactory
方法是一个黑匣子,我们只关注入参和出参,并不关注具体如何实现,对应到策略模式上就是我们的客户端只关注Context类 并不关注Context中是如何实现的,
从一开始按照原价付费
到后来能够打折
到后来能够满减
策略模式可以解决人们日益增长的需求,从有限需求要无限需求的跨越,使用面向对象的思考方式都能解决。