110.【十万字带你深入学习23种设计模式】(二十)

简介: 110.【十万字带你深入学习23种设计模式】
(4).使用场景

优点:

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

缺点:

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

使用场景:

  • 一个系统需要动态的在几种算法中选择一种时,可将算法封装到策略类中
  • 一个类定义了多种行为,并且这些行为在这个类中的操作以多个条件语句的形式出现,可将每个条件分支一如他们各自的策略类中以代替这些条件语句
  • 系统中各个算法彼此完全独立,且要求对用户隐藏具体算法的实现细节时。
  • 系统要求使用算法的客户不应该知道其操作的数据时,可使用策略模式来隐藏与算法相关的数据结构
  • 多个类只区别在表现型为不同,可以使用策略模式,在运行时动态选择具体执行的行为。
(5).JDK源码解析

Comparator中的策略模式在Arrays类中有一个Sort()方法。

1. sort()方法时排序的方法
2. 每一个排序的方法后面都对应着不同的算法,升序和降序算法。

3.命令模式

(1).命令模式

日常生活中,我们出去吃饭会遇到如下的情况。

顾客(点餐)->女服务员(接受订单)->女服务员转给厨师(厨师佐餐)

定义:

将一个请求封装为对象,使发出请求的责任(服务员)执行请求的责任(厨师)分隔开。这样两者之间通过命令对象进行沟通,这样方便命令对象进行存储、传递、调用、增加与管理

(2).结构

命令模式包含以下主要角色:

  • 抽象命令角色: 定义命令的接口,声明执行的方法。
  • 具体命令角色: 具体的命令,实现命令接口;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。
  • 实现者/接收者角色: 接收者,真正执行命令的对象(厨师)。任何类都可以成为一个接收者,只要它能够实现命令要求实现的响应功能。
  • 调用者/请求者角色: 要求命令对象执行请求(服务员),通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行响应的操作的地方,也就是说相当于使用命令对象的入口。
(3).案列实现

将上面的案列用代码实现,那我们就需要分析命令模式的角色在该案列中由谁来充当。

服务员: 调用者角色。

资深大厨: 结接收者角色。

订单: 命令中包含订单。

订单

package com.jsxs.behavioralModel.command;
import java.util.HashMap;
import java.util.Map;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:08
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: Order
 * @Description: TODO 订单类
 * @Version 1.0
 */
public class Order {
    // 餐桌号码
    private int diningTable;
    // 所属的餐品及分数
  private Map<String,Integer> foodDir=new HashMap<String,Integer>();
    public int getDiningTable() {
        return diningTable;
    }
    public void setDiningTable(int diningTable) {
        this.diningTable = diningTable;
    }
    public Map<String, Integer> getFoodDir() {
        return foodDir;
    }
    // 餐品的名称和数量
    public void setFood(String name,int num) {
        foodDir.put(name,num);
    }
}

接收者

package com.jsxs.behavioralModel.command;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:15
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: SeniorChef
 * @Description: TODO  厨师
 * @Version 1.0
 */
public class SeniorChef {
    // 做餐
    public void makeFood(String name,int num){
        System.out.println(num+" 份 "+name);
    }
}

抽象命令

package com.jsxs.behavioralModel.command;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:16
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: Command
 * @Description: TODO  抽象命令类
 * @Version 1.0
 */
public interface Command {
    void execute();  //执行命令
}

具体命令

package com.jsxs.behavioralModel.command;
import java.util.Map;
import java.util.Set;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:17
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: OrderCommand
 * @Description: TODO
 * @Version 1.0
 */
public class OrderCommand implements Command{
    // 持有接收者对象
    private SeniorChef seniorChef;
    // 持有订单对象
    private Order order;
    // 有参构造方法进行赋值的操作
    public OrderCommand(SeniorChef seniorChef, Order order) {
        this.seniorChef = seniorChef;
        this.order = order;
    }
    //
    @Override
    public void execute() {
        System.out.println(order.getDiningTable()+"号桌的订单是:");
        // 这里存放的是我们要做的全部餐品
        Map<String, Integer> foodDir = order.getFoodDir();
        // 遍历map集合
        Set<String> strings = foodDir.keySet();  //获取所有键的集合
        // 做餐
        for (String foodName : strings) {
            seniorChef.makeFood(foodName,foodDir.get(foodName));  // 餐名和数量
        }
        System.out.println(order.getDiningTable()+"号桌子的饭做好了");
    }
}

请求者

package com.jsxs.behavioralModel.command;
import java.util.ArrayList;
import java.util.List;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:27
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: Waitor
 * @Description: TODO  服务员 (请求者角色)
 * @Version 1.0
 */
public class Waitor {
    // 持有多个命令对象
    private List<Command> commands = new ArrayList<>();
    // 将单个命令存放到集合中
    public void setCommand(Command command) {
        commands.add(command);
    }
    // 发起命令的功能
    public void orderUp(){
        System.out.println("美女服务员说: 来订单了...");
        // 因为命令在集合中
        for (Command command : commands) {
            if (command!=null){
                command.execute(); // 执行
            }
        }
    }
}

测试类

package com.jsxs.behavioralModel.command;
/**
 * @Author Jsxs
 * @Date 2023/4/23 13:32
 * @PackageName:com.jsxs.behavioralModel.command
 * @ClassName: Client
 * @Description: TODO
 * @Version 1.0
 */
public class Client {
    public static void main(String[] args) {
        // 订单对象
        Order order1 = new Order();
        order1.setDiningTable(1);
        order1.setFood("西红柿鸡蛋面",1);
        order1.setFood("可乐",2);
        Order order2 = new Order();
        order2.setDiningTable(2);
        order2.setFood("炒饭",1);
        order2.setFood("雪碧",2);
        // 创建厨师对象
        SeniorChef seniorChef = new SeniorChef();
        // 创建命令对象
        OrderCommand orderCommand = new OrderCommand(seniorChef, order1);
        OrderCommand orderCommand2 = new OrderCommand(seniorChef, order2);
        //创建调用者也就是服务员
        Waitor waitor = new Waitor();
        waitor.setCommand(orderCommand);
        waitor.setCommand(orderCommand2);
        waitor.orderUp();
    }
}

(4).使用场景

优点:

  1. 降低了系统的耦合度,命令模式能将调用操作的对象与实现该操作的对象解耦。
  2. 增加或删除命令非常方便。采用命令模式增加或删除命令不会影响其他类,它满足"开闭原",对扩展比较灵活。
  3. 可以实现宏命令。命令模式可以与组合模式结合,将多个命令装配成一个组合命令,即宏命令。
  4. 方便实现 Undo(命令撤销) 和 Redo(命令恢复) 操作。命令模式可以与后面介绍的备忘录模式结合,实现命令的撤销与恢复。

缺点:

  1. 使用命令模式可能会导致某些系统有过多的具体命令类。
  2. 系统结构更加复杂

使用场景:

  • 系统需要将请求调用者和请求接受者解耦,使得调用者和接收者部直接交互。
  • 系统需要在不同的事件指定请求、将请求排队(List)和执行请求。
  • 系统需要支持命令的撤销操作(Undo)和恢复操作(Redo).
(5).JDK源码解析

Runable是一个典型的命令模式,Runnable担当命令的角色,Thread(服务员)充当的是调用者,start方法就是执行方法。

相关文章
|
10月前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
143 0
|
9月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
65 2
|
9月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
70 2
|
10月前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
9月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
57 0
|
9月前
|
设计模式 数据可视化 程序员
设计模式学习心得之前置知识 UML图看法与六大原则(上)
设计模式学习心得之前置知识 UML图看法与六大原则(上)
76 0
|
10月前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
10月前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
10月前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
10月前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
107 0