设计模式之【策略模式】,去掉繁琐的if-else,实现算法的动态替换

这篇具有很好参考价值的文章主要介绍了设计模式之【策略模式】,去掉繁琐的if-else,实现算法的动态替换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


全网最全最细的【设计模式】总目录,收藏起来慢慢啃,看完不懂砍我

一、什么是策略模式

策略模式(Strategy Pattern)又叫政策模式(Policy Pattern),它是将定义的算法家族分别封装起来,让它们之间可以互相替换,从而让算法的变化不会影响到使用算法的用户。属于行为型模式。

策略模式使用的就是面向对象的继承和多态机制,从而实现同一行为在不同场景下具备不同实现。

1、策略模式应用场景

策略模式在生活中应用也非常多。比如一个人的交税比率与他的工资有关,不同工资对应不同的税率。再比如互联网移动支付,每次下单后付款都需要选择支付方式。

策略模式可以解决在有多种算法相似的情况下,使用if-else或者switch-case所带来的复杂性和臃肿性,策略模式通常适用于以下场景:

  • 针对同一类型问题,有多种处理方式,每一种都能独立解决问题;
  • 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现,可将每个条件分支移入它们各自的策略类中以代替这些条件语句;
  • 多个类只区别在表现行为不同,可以使用策略模式,在运行时动态选择具体要执行的行为;
  • 算法需要自由切换的场景;
  • 需要屏蔽算法规则的场景。

2、状态模式与策略模式的区别

状态模式和策略模式的UML类图架构几乎完全一样,但他们的应用场景是不一样的。策略模式多种算法行为择其一都能满足,彼此之间是独立的,用户可自行更换策略算法;而状态模式各个状态间是存在相互关系的,彼此之间在一定条件下存在自动切换状态效果,且用户无法指定状态,只能设置初始状态。

3、策略模式优缺点

优点:

  • 策略类之间可以自由切换:由于策略类都实现同一个接口,所以使它们之间可以自由切换。
  • 易于扩展:增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则“
  • 避免使用多重条件选择语句(if else),充分体现面向对象设计思想。

缺点:

  • 客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
  • 策略模式将造成产生很多策略类,可以通过使用享元模式在一定程度上减少对象的数量。

4、策略模式的三大角色

策略模式消除ifelse,设计模式与开发规范,策略模式,设计模式,算法
策略模式的主要角色如下:

  • 抽象策略(Strategy)类:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
  • 具体策略(Concrete Strategy)类:实现了抽象策略定义的接口,提供具体的算法实现或行为。
  • 环境(Context)类:用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略、算法的直接访问,封装可能存在的变化。

注:策略模式中的上下文环境(Context),其职责本来是隔离客户端与策略类的耦合,让客户端完全与上下文环境沟通,无需关心具体策略。

二、实例

1、策略模式的一般写法

//抽象策略类 Strategy
public interface IStrategy {
    void algorithm();
}
//具体策略类 ConcreteStrategy
public class ConcreteStrategyA implements IStrategy {
    public void algorithm() {
        System.out.println("Strategy A");
    }
}
//具体策略类 ConcreteStrategy
public class ConcreteStrategyB implements IStrategy {
    public void algorithm() {
        System.out.println("Strategy B");
    }
}
//上下文环境
public class Context {
    private IStrategy mStrategy;

    public Context(IStrategy strategy) {
        this.mStrategy = strategy;
    }

    public void algorithm() {
        this.mStrategy.algorithm();
    }
}
public class Test {
    public static void main(String[] args) {
        //选择一个具体策略
        IStrategy strategy = new ConcreteStrategyA();
        //来一个上下文环境
        Context context = new Context(strategy);
        //客户端直接让上下文环境执行算法
        context.algorithm();
    }
}

2、促销活动案例

一家百货公司在定年度的促销活动。针对不同的节日(春节、中秋节、圣诞节)推出不同的促销活动,由促销员将促销活动展示给客户。类图如下:
策略模式消除ifelse,设计模式与开发规范,策略模式,设计模式,算法

// 定义百货公司所有促销活动的共同接口
public interface Strategy {
	void show();
}
// 定义具体策略角色(Concrete Strategy):每个节日具体的促销活动
//为春节准备的促销活动A
public class StrategyA implements Strategy {
	public void show() {
		System.out.println("买一送一");
	}
}
//为中秋准备的促销活动B
public class StrategyB implements Strategy {
	public void show() {
		System.out.println("满200元减50元");
	}
}
//为圣诞准备的促销活动C
public class StrategyC implements Strategy {
	public void show() {
		System.out.println("满1000元加一元换购任意200元以下商品");
	}
}
// 定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员
public class SalesMan {
	//持有抽象策略角色的引用
	private Strategy strategy;
	public SalesMan(Strategy strategy) {
		this.strategy = strategy;
	}
	//向客户展示促销活动
	public void salesManShow(){
		strategy.show();
	}
}
// 测试类
public class Client {
    public static void main(String[] args) {
        //春节来了,使用春节促销活动
        SalesMan salesMan = new SalesMan(new StrategyA());
        //展示促销活动
        salesMan.salesManShow();

        System.out.println("==============");
        //中秋节到了,使用中秋节的促销活动
        salesMan.setStrategy(new StrategyB());
        //展示促销活动
        salesMan.salesManShow();

        System.out.println("==============");
        //圣诞节到了,使用圣诞节的促销活动
        salesMan.setStrategy(new StrategyC());
        //展示促销活动
        salesMan.salesManShow();
    }
}

此时,我们发现,上面的测试代码放到实际业务场景其实并不实用,因为我们做活动时往往是要根据不同的需求对促销策略进行动态选择的,并不会一次性执行多种优惠,所以我们代码通常会这样写:

public class Client {
    public static void main(String[] args) {
        SalesMan salesMan = null;
        String saleKey = "A";
        
        if(saleKey.equals("A")){
            //春节来了,使用春节促销活动
            salesMan = new SalesMan(new StrategyA());
        } else if (saleKey.equals("B")) {
            //中秋节到了,使用中秋节的促销活动
            salesMan = new SalesMan(new StrategyB());
        } // ...

        //展示促销活动
        salesMan.salesManShow();
    }
}

这样改造之后,满足了业务需求,客户可以根据自己的需求选择不同的优惠策略了。但是这里的if-else随着促销活动的增多会越来越复杂,我们可以使用单例模式和工厂模式进行优化:

public class SalesMan {

    public static final String SaleKeyA = "A";
    public static final String SaleKeyB = "B";
    public static final String SaleKeyC = "C";

    private static Map<String, Strategy> sales = new HashMap<String, Strategy>();

    static {
        sales.put(SaleKeyA, new StrategyA());
        sales.put(SaleKeyB, new StrategyB());
        sales.put(SaleKeyC, new StrategyC());
    }

    public Strategy getStrategy(String key) {
        Strategy strategy = sales.get(key);
        if(strategy == null){
            throw new RuntimeException("策略有误");
        }
        return strategy;
    }
}

public class Client {
    public static void main(String[] args) {
        SalesMan salesMan = new SalesMan();
        String saleKey = "A";

        Strategy strategy = salesMan.getStrategy(saleKey);

        //展示促销活动
        strategy.show();
    }
}

3、网购订单支付案例

我们在网购下单时,会提示选择支付方式,通常会有支付宝、微信、银联等等支付方式,如果没选择,系统也会使用默认的支付方式,我们使用策略模式来模拟此场景:

// 支付状态包装类
public class MsgResult {
    private int code;
    private Object data;
    private String msg;

    public MsgResult(int code, String msg, Object data) {
        this.code = code;
        this.data = data;
        this.msg = msg;
    }

    @Override
    public String toString() {
        return "MsgResult{" +
                "code=" + code +
                ", data=" + data +
                ", msg='" + msg + '\'' +
                '}';
    }
}

// 定义支付逻辑,具体支付交由子类实现
public abstract class Payment {

    public abstract String getName();

    //通用逻辑放到抽象类里面实现
    public MsgResult pay(String uid, double amount){
        //余额是否足够
        if(queryBalance(uid) < amount){
            return new MsgResult(500,"支付失败","余额不足");
        }
        return new MsgResult(200,"支付成功","支付金额" + amount);
    }

    protected abstract double queryBalance(String uid);
}

// 定义具体支付方式
public class AliPay extends Payment {
    public String getName() {
        return "支付宝";
    }

    protected double queryBalance(String uid) {
        return 900;
    }
}
public class JDPay extends Payment {
    public String getName() {
        return "京东白条";
    }

    protected double queryBalance(String uid) {
        return 500;
    }
}
public class UnionPay extends Payment {
    public String getName() {
        return "银联支付";
    }

    protected double queryBalance(String uid) {
        return 120;
    }
}
public class WechatPay extends Payment {
    public String getName() {
        return "微信支付";
    }

    protected double queryBalance(String uid) {
        return 263;
    }
}

// 策略管理类
public class PayStrategy {
    public static  final String ALI_PAY = "AliPay";
    public static  final String JD_PAY = "JdPay";
    public static  final String WECHAT_PAY = "WechatPay";
    public static  final String UNION_PAY = "UnionPay";
    public static  final String DEFAULT_PAY = ALI_PAY;

    private static Map<String,Payment> strategy = new HashMap<String,Payment>();

    static {
        strategy.put(ALI_PAY,new AliPay());
        strategy.put(JD_PAY,new JDPay());
        strategy.put(WECHAT_PAY,new WechatPay());
        strategy.put(UNION_PAY,new UnionPay());
    }

    public static Payment get(String payKey){
        if(!strategy.containsKey(payKey)){
            return strategy.get(DEFAULT_PAY);
        }
        return strategy.get(payKey);
    }
}

// 订单类
public class Order {
    private String uid;
    private String orderId;
    private double amount;

    public Order(String uid, String orderId, double amount) {
        this.uid = uid;
        this.orderId = orderId;
        this.amount = amount;
    }

    public MsgResult pay(){
        return pay(PayStrategy.DEFAULT_PAY);
    }

    public MsgResult pay(String payKey){
        Payment payment = PayStrategy.get(payKey);
        System.out.println("欢迎使用" + payment.getName());
        System.out.println("本次交易金额为" + amount + ",开始扣款");
        return payment.pay(uid,amount);
    }
}

// 测试类
public class Test {
    public static void main(String[] args) {
        Order order = new Order("1","orderid",324.5);
        System.out.println(order.pay(PayStrategy.UNION_PAY));
    }
}

4、DispatcherServlet的优化

我们都知道SpringMVC的请求都是通过DispatcherServlet的doDispatch方法进行分发的,如果让我们设计,可能会这样实现:

public class DispatcherServlet extends HttpServlet {

	private void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

		String uri = request.getRequestURI();
		String mid = request.getParameter("mid");
		if("getMemberById".equals(uri)){
			new MemberController().getMemberById(mid);
		} else if("getOrder".equals(uri)) {
			new OrderController().getOrder();
		}// ...
	}

}

上面的代码扩展性确实不太优雅,我们可以使用策略模式进行优化:

public class DispatcherServlet extends HttpServlet {

    private List<Handler> handlerMapping = new ArrayList<Handler>();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doDispatch(req,resp);
    }

    private void doDispatch(HttpServletRequest req, HttpServletResponse resp) {
        String uri = req.getRequestURI();
        // 使用uri匹配handler
        Handler handler = null;
        for (Handler h : handlerMapping) {
            if(uri.equals(h.getUrl())){
                handler = h;
                break;
            }
        }
        // 将具体任务分发给Method
        Object result = null;
        try {
            result = handler.getMethod().invoke(handler.getController());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        
        // 写回结果
        try {
            resp.getWriter().write((String) result);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void init() throws ServletException {
        try {
            
            handlerMapping.add(new Handler().setController(MemberController.class.newInstance())
                            .setMethod(MemberController.class.getMethod("getMemberById", new Class[]{String.class}))
                            .setUrl("/web/getMemberById.json"));
            handlerMapping.add(new Handler().setController(OrderController.class.newInstance())
                            .setMethod(OrderController.class.getMethod("getOrderById", new Class[]{String.class}))
                            .setUrl("/web/getOrderById.json"));
            // ...其他handler
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

class Handler {
    private Object controller;
    private Method method;
    private String url;

    public Object getController() {
        return controller;
    }

    public Handler setController(Object controller) {
        this.controller = controller;
        return this;
    }

    public Method getMethod() {
        return method;
    }

    public Handler setMethod(Method method) {
        this.method = method;
        return this;
    }

    public String getUrl() {
        return url;
    }

    public Handler setUrl(String url) {
        this.url = url;
        return this;
    }
}

5、文件排序案例

我们再使用一个文件排序的案例加深策略模式的印象。

有这样一个需求,希望写一个小程序,实现对一个文件进行排序的功能。不同大小的文件排序的算法是不同的,我们初步可能会这样实现:

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    if (fileSize < 6 * GB) { // [0, 6GB)
      quickSort(filePath);
    } else if (fileSize < 10 * GB) { // [6GB, 10GB)
      externalSort(filePath);
    } else if (fileSize < 100 * GB) { // [10GB, 100GB)
      concurrentExternalSort(filePath);
    } else { // [100GB, ~)
      mapreduceSort(filePath);
    }
  }
  private void quickSort(String filePath) {
    // 快速排序
  }
  private void externalSort(String filePath) {
    // 外部排序
  }
  private void concurrentExternalSort(String filePath) {
    // 多线程外部排序
  }
  private void mapreduceSort(String filePath) {
    // 利用MapReduce多机排序
  }
}
public class SortingTool {
  public static void main(String[] args) {
    Sorter sorter = new Sorter();
    sorter.sortFile(args[0]);
  }
}

以上代码并不能体现面向对象的魅力,完全是面向过程的,而我们日常开发中这样的代码也是占大多数。

我们使用策略模式进行重构:

// 策略接口
public interface ISortAlg {
  void sort(String filePath);
}
// 具体策略类
public class QuickSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}
public class ExternalSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}
public class ConcurrentExternalSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}
public class MapReduceSort implements ISortAlg {
  @Override
  public void sort(String filePath) {
    //...
  }
}
// 排序
public class SortAlgFactory {
  private static final Map<String, ISortAlg> algs = new HashMap<>();
  static {
    algs.put("QuickSort", new QuickSort());
    algs.put("ExternalSort", new ExternalSort());
    algs.put("ConcurrentExternalSort", new ConcurrentExternalSort());
    algs.put("MapReduceSort", new MapReduceSort());
  }
  public static ISortAlg getSortAlg(String type) {
    if (type == null || type.isEmpty()) {
      throw new IllegalArgumentException("type should not be empty.");
    }
    return algs.get(type);
  }
}
public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg;
    if (fileSize < 6 * GB) { // [0, 6GB)
      sortAlg = SortAlgFactory.getSortAlg("QuickSort");
    } else if (fileSize < 10 * GB) { // [6GB, 10GB)
      sortAlg = SortAlgFactory.getSortAlg("ExternalSort");
    } else if (fileSize < 100 * GB) { // [10GB, 100GB)
      sortAlg = SortAlgFactory.getSortAlg("ConcurrentExternalSort");
    } else { // [100GB, ~)
      sortAlg = SortAlgFactory.getSortAlg("MapReduceSort");
    }
    sortAlg.sort(filePath);
  }
}

Sorter 类中的 sortFile() 函数还是有一堆 if-else 逻辑。这里的 if-else 逻辑分支不多、也不复杂,这样写完全没问题。但如果你特别想将 if-else 分支判断移除掉,那也是有办法的。我直接给出代码,你一看就能明白。实际上,这也是基于查表法来解决的,其中的“algs”就是“表”。

public class Sorter {
  private static final long GB = 1000 * 1000 * 1000;
  private static final List<AlgRange> algs = new ArrayList<>();
  static {
    algs.add(new AlgRange(0, 6*GB, SortAlgFactory.getSortAlg("QuickSort")));
    algs.add(new AlgRange(6*GB, 10*GB, SortAlgFactory.getSortAlg("ExternalSort")));
    algs.add(new AlgRange(10*GB, 100*GB, SortAlgFactory.getSortAlg("ConcurrentExternalSort")));
    algs.add(new AlgRange(100*GB, Long.MAX_VALUE, SortAlgFactory.getSortAlg("MapReduceSort")));
  }
  public void sortFile(String filePath) {
    // 省略校验逻辑
    File file = new File(filePath);
    long fileSize = file.length();
    ISortAlg sortAlg = null;
    for (AlgRange algRange : algs) {
      if (algRange.inRange(fileSize)) {
        sortAlg = algRange.getAlg();
        break;
      }
    }
    sortAlg.sort(filePath);
  }
  private static class AlgRange {
    private long start;
    private long end;
    private ISortAlg alg;
    public AlgRange(long start, long end, ISortAlg alg) {
      this.start = start;
      this.end = end;
      this.alg = alg;
    }
    public ISortAlg getAlg() {
      return alg;
    }
    public boolean inRange(long size) {
      return size >= start && size < end;
    }
  }
}

6、Spring中策略模式简单应用

策略模式在实际开发中的应用

@Autowired
private Map<String,MyService> ServiceMap;

@Slf4j
@Service("MyServiceImpl")
public class MyServiceImpl implements MyService {}

Spring在自动注入时,使用Map的话,key就是接口实现类Bean的名称,value就是对应的Bean实例。

三、源码中的策略模式

1、Comparator接口

JDK中一个常用的比较器Comparator接口,有一个常用的方法compare():

public interface Comparator<T> {
	int compare(T o1, T o2);
}

Comparator抽象下面有非常多的实现类,我们经常会把Comparator作为参数传入作为排序策略,例如Arrays类的parallelSort方法等:

public class Arrays{
	public static <T> void sort(T[] a, Comparator<? super T> c) {
		if (c == null) {
		sort(a);
		} else {
		if (LegacyMergeSort.userRequested)
		legacyMergeSort(a, c);
		else
		TimSort.sort(a, 0, a.length, c, null, 0, 0);
		}
	}
}

Arrays就是一个环境角色类,这个sort方法可以传一个新策略让Arrays根据这个策略来进行排序。就比如下面的测试类。

public class demo {
	public static void main(String[] args) {
		Integer[] data = {12, 2, 3, 2, 4, 5, 1};
		// 实现降序排序
		Arrays.sort(data, new Comparator<Integer>() {
		public int compare(Integer o1, Integer o2) {
		return o2 - o1;
		}
		});
		System.out.println(Arrays.toString(data)); //[12, 5, 4, 3, 2, 2, 1]
	}
}

这里我们在调用Arrays的sort方法时,第二个参数传递的是Comparator接口的子实现类对象。所以Comparator充当的是抽象策略角色,而具体的子实现类充当的是具体策略角色。环境角色类(Arrays)应该持有抽象策略的引用来调用。那么,Arrays类的sort方法到底有没有使用
Comparator子实现类中的 compare() 方法吗?让我们继续查看TimSort类的 sort() 方法,代码如下:

static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
                     T[] work, int workBase, int workLen) {
    assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;

    int nRemaining  = hi - lo;
    if (nRemaining < 2)
        return;  // Arrays of size 0 and 1 are always sorted

    // If array is small, do a "mini-TimSort" with no merges
    if (nRemaining < MIN_MERGE) {
        int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
        binarySort(a, lo, hi, lo + initRunLen, c);
        return;
    }

    /**
     * March over the array once, left to right, finding natural runs,
     * extending short natural runs to minRun elements, and merging runs
     * to maintain stack invariant.
     */
    TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen);
    int minRun = minRunLength(nRemaining);
    do {
        // Identify next run
        int runLen = countRunAndMakeAscending(a, lo, hi, c);

        // If run is short, extend to min(minRun, nRemaining)
        if (runLen < minRun) {
            int force = nRemaining <= minRun ? nRemaining : minRun;
            binarySort(a, lo, lo + force, lo + runLen, c);
            runLen = force;
        }

        // Push run onto pending-run stack, and maybe merge
        ts.pushRun(lo, runLen);
        ts.mergeCollapse();

        // Advance to find next run
        lo += runLen;
        nRemaining -= runLen;
    } while (nRemaining != 0);

    // Merge all remaining runs to complete sort
    assert lo == hi;
    ts.mergeForceCollapse();
    assert ts.stackSize == 1;
}

上面的代码中最终会跑到 countRunAndMakeAscending() 这个方法中。我们可以看见,只用了compare方法,所以在调用Arrays.sort方法只传具体compare重写方法的类对象就行,这也是Comparator接口中必须要子类实现的一个方法。

2、Spring的InstantiationStrategy

Spring初始化用到的InstantiationStrategy接口:

public interface InstantiationStrategy {

	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner)
			throws BeansException;

	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			Constructor<?> ctor, Object... args) throws BeansException;

	Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Object factoryBean, Method factoryMethod, Object... args)
			throws BeansException;

}

它有两种策略:CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy,我们发现了CglibSubclassingInstantiationStrategy继承了SimpleInstantiationStrategy,说明在实际应用中多种策略之间还可以继承使用。我们可以作为一个参考,在实际业务场景中,可以根据需要进行设计。

3、Spring的Resource

package org.springframework.core.io;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.springframework.lang.Nullable;

public interface Resource extends InputStreamSource {

	boolean exists();

	default boolean isReadable() {
		return exists();
	}

	default boolean isOpen() {
		return false;
	}

	default boolean isFile() {
		return false;
	}

	URL getURL() throws IOException;

	URI getURI() throws IOException;

	File getFile() throws IOException;

	default ReadableByteChannel readableChannel() throws IOException {
		return Channels.newChannel(getInputStream());
	}

	long contentLength() throws IOException;

	long lastModified() throws IOException;

	Resource createRelative(String relativePath) throws IOException;

	@Nullable
	String getFilename();

	String getDescription();

}

Resource有很多子类:
策略模式消除ifelse,设计模式与开发规范,策略模式,设计模式,算法文章来源地址https://www.toymoban.com/news/detail-707086.html

到了这里,关于设计模式之【策略模式】,去掉繁琐的if-else,实现算法的动态替换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式:干掉if else的几种方法

    存在的问题: 如果业务逻辑过多 if else 可能要写多达几百行,这样代码可读性很差,不利于寻找bug和理解代码 如果if后面的判断逻辑过长,则代码可读性不强 如果将其写在一个核心代码里面,则新增功能时需要修改核心代码,要是不小心改到其他的代码就凉凉了 当业务逻辑

    2024年02月07日
    浏览(41)
  • 【状态模式】拯救if-else堆出来的屎山代码

    我想大家平时都在开发重都遇见过屎山代码,这些屎山代码一般都是由于复杂且庞大的if-else造成的,状态模式,是一种很好的优化屎山代码的设计模式,本文将采用两个业务场景的示例来讲解如何使用状态模式拯救屎山代码。 目录 前言 1.网购业务场景 1.1.需求 1.2.if else的实

    2024年02月12日
    浏览(40)
  • 设计模式第八讲:常见重构技巧 - 去除多余的if else

    最为常见的是代码中使用很多的if/else,或者switch/case;如何重构呢?方法特别多,本文是设计模式第八讲,带你学习其中的技巧。 通常业务代码会包含这样的逻辑:每种条件下会有不同的处理逻辑。比如两个数a和b之间可以通过不同的操作符(+,-,*,/)进行计算,初学者通

    2024年02月10日
    浏览(41)
  • Python if-else 速记

    编程中经常使用速记符号来简化我们的工作。 速记符号是一种可以更简洁、更省时省力地完成工作的方法。 本文将讨论 Python 中使用的速记符号作为 if-else 语句的快捷方式。 如前所述,速记符号是一种可以简洁地编写程序的方法。 到目前为止,我们在 Python 中使用了许多速

    2024年02月11日
    浏览(43)
  • Python用if-else实现【猜数字】

    设置一个 范围1-100的随机整数变量 ,通过 while 循环,配合 input 语句,判断输入的数字是否等于随机数 无限次机会,直到猜中为止 每一次猜不中,会提示大了或小了 猜完数字后,提示猜了几次 提示: 无限次机会,终止条件不适合用数字累加来判断 可以考虑布尔类型本身 (

    2024年02月12日
    浏览(38)
  • 策略模式+Spring配置类优化多if..else思路

    场景: 假设设备上报不同类型的消息,我们要对不同类型的消息做不同的处理。如果我们通过if..else的方式处理的话会显得比较冗余。 例如: 那么对于不同消息的不同的处理逻辑我们可以单独放在一个实现类中,这些类有着相同的行为,所以我们可以定义一个接口: 针对于不

    2024年02月15日
    浏览(43)
  • mybatis使用xml中的if-else/choose

    最近需要使用 xml 文件来实现一些增删改查,此文对 其中的 if-else 加以说明 背景: 有一个引用类,假设叫 Student 现在我们查询条件也被封装成一个引用类,例如: 那么使用 xml 怎么来使用和接收呢? 首先肯定是在 mapper 里面有一个方法 然后在 xml 文件中写这个方法的具体实

    2024年04月23日
    浏览(38)
  • 不需要策略模式也能避免满屏if/else

    java 复制代码 public static void main(String[] args) { int a = 1; if(a == 1){ System.out.println(\\\"执行a=1的逻辑\\\"); }else if (a == 2){ System.out.println(\\\"执行a=2的逻辑\\\"); }else if (a == 3){ System.out.println(\\\"执行a=3的逻辑\\\"); }else if (a == 4){ System.out.println(\\\"执行a=4的逻辑\\\"); }else if (a == 5){ System.out.println(\\\"执行a=5的逻辑

    2024年02月06日
    浏览(89)
  • 条件运算符? : 与if-else语句的对比及用法详解

    条件运算符? : :给程序员提供了一种简便的方式进行条件判断和表达式的求值。在C语言中,条件运算符? : 是一个三元运算符,可以根据条件的真假来判断输出结果。本篇文章将详细介绍条件运算符的用法,以及与if-else语句的对比,并结合实例来进一步理解。 条件运算符?

    2024年02月05日
    浏览(52)
  • Verilog 不完整if-else和case产生锁存latch

    写这篇文章是因为本小白在刷题过程中看到答主的代码总是不把if-else写全,而我又记得不写全是可能产生latch的,对此很迷惑,仔细看过之后发现只有组合逻辑(电平触发)电路中的不完整if-else和case才会产生锁存器latch。简单记录一下。 参考文章: 1、https://blog.csdn.net/ainu

    2024年02月13日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包