Exemplo de uso do modo de comando-modo de design em teclas de função personalizadas do programa Java-desktop

Cenas

Para desenvolver uma versão desktop do aplicativo, o aplicativo fornece aos usuários uma série de teclas de função personalizadas, os usuários podem usar essas teclas de função para realizar algumas operações de atalho.

Os usuários podem vincular teclas de função e funções correspondentes e também modificar a configuração das teclas de função de acordo com as necessidades, e o sistema pode adicionar algumas novas funções ou teclas de função no futuro.

Isso é possível se você não usar o padrão Command.

A classe de chave de função FunctionButton atua como remetente da solicitação, e a classe de processamento de documentos de ajuda HelpHandler atua como receptor da solicitação, no onClick() do remetente FunctionButton

chamará o método display() do HelpHandler do receptor.

Botão de função:

public class FunctionButton {
    //帮助文档处理类,请求接收者
    private HelpHandler helperHandler;

    public void onClick(){
        helperHandler = new HelpHandler();
        //显示帮助文档
        helperHandler.display();
    }
}

Manipulador de ajuda:

public class HelpHandler {
    public void display(){
        System.out.println("显示帮助文档");
    }
}

Problemas com o acima:

(1) Como existe uma chamada de método direta entre o remetente e o destinatário da solicitação, o grau de acoplamento é muito alto e o código-fonte do remetente deve ser modificado para substituir o receptor da solicitação.

Se você precisar alterar o receptor de solicitação HelpHandler para WindowHanlder (classe de manipulação de janela), será necessário modificar o código-fonte do FunctionButton, que viola o "princípio de abertura e fechamento".

(2) A função da classe FunctionButton foi corrigida durante o design e implementação.Se um novo receptor de solicitação for adicionado, se a classe FunctionButton original não for modificada,

Em seguida, uma nova classe semelhante a FunctionButton deve ser adicionada, o que levará a um aumento acentuado no número de classes no sistema.

Como pode não haver nenhum relacionamento entre o receptor de solicitação HelpHandler, WindowHanlder e outras classes, eles não possuem uma camada de abstração comum,

Portanto, também é difícil projetar FunctionButton de acordo com o "princípio de inversão de dependência".

(3) Os usuários não podem definir a função de uma tecla de função de acordo com suas próprias necessidades. Uma vez que a função de uma tecla de função é fixada, sua função não pode ser alterada sem modificar o código-fonte.

O sistema carece de flexibilidade.

Visão geral do padrão de comando

No desenvolvimento de software, muitas vezes precisamos enviar solicitações para alguns objetos (chamar um ou mais métodos), mas não sabemos quem é o destinatário da solicitação.

Não sei qual operação é solicitada. Neste momento, esperamos especialmente projetar o software de forma fracamente acoplada, de modo que o remetente e o destinatário da solicitação

Ele pode eliminar o acoplamento entre si, tornar o relacionamento de chamada entre objetos mais flexível e especificar com flexibilidade o receptor da solicitação e a operação solicitada.

O modo de comando oferece uma solução mais perfeita para tais problemas.

O modo de comando pode dissociar completamente o remetente e o destinatário da solicitação. Não há relação de referência direta entre o remetente e o destinatário. O objeto que envia a solicitação só precisa saber como enviar a solicitação.

sem precisar saber como concluir a solicitação.

Padrão de Comando:

Encapsular uma solicitação como um objeto nos permite parametrizar clientes com diferentes solicitações; enfileirar solicitações ou registrar logs de solicitações e oferecer suporte a operações que podem ser revertidas.

O modo de comando é um modo de comportamento de objeto, seu alias é o modo de ação (Ação) ou o modo de transação (Transação).

Diagrama da estrutura do modo de comando

As funções incluídas no modo de comando:

Comando (classe de comando abstrata):

A classe de comando abstrata é geralmente uma classe ou interface abstrata, na qual são declarados métodos como execute() para executar solicitações,

Através destes métodos, operações relacionadas do receptor de solicitação podem ser invocadas.

ConcreteCommand (classe de comando específica):

A classe de comando concreta é uma subclasse da classe de comando abstrata, que implementa os métodos declarados na classe de comando abstrata e corresponde ao objeto receptor específico.

Vincule as ações do objeto receptor a ele. Ao implementar o método execute(), a operação relevante (Action) do objeto receptor será chamada.

Invocador (chamador):

O chamador é o remetente da solicitação e a executa por meio do objeto de comando. Um chamador não precisa determinar seu receptor em tempo de design,

Portanto, está associado apenas à classe de comando abstrata. Um objeto de comando específico pode ser injetado no programa quando ele está em execução,

Em seguida, chame o método execute() do objeto de comando específico, de modo a realizar as operações relacionadas do receptor de chamada indireta.

Receptor:

O receptor executa operações relacionadas à solicitação e implementa o processamento comercial da solicitação. A essência do modo de comando é encapsular a solicitação,

Uma solicitação corresponde a um comando, separando a responsabilidade pela emissão do comando da responsabilidade pela execução do comando. Cada comando é uma operação:

A parte solicitante envia uma solicitação para realizar uma operação; a parte receptora recebe a solicitação e executa a operação correspondente.

O modo de comando permite que a parte solicitante e a parte receptora sejam independentes, de modo que a parte solicitante não precise conhecer a interface da parte receptora,

Não é necessário saber como a solicitação é recebida, se a operação é realizada, quando é realizada e como é realizada.

Observação:

Blog:
Domineering Rogue Temperament_C#, Architecture Road, SpringBoot-CSDN Blog

concluir

Use o modo de comando para implementar as teclas de função definidas pelo usuário acima.

1. Crie uma nova classe de comando abstrata

//抽象命令类
abstract class Command {
    public abstract void execute();
}

2. Crie uma nova classe de comando específica: classe de comando de ajuda

//帮助命令类:具体命令类
public class HelpCommand extends Command{

    //维持对请求接收者的引用
    private HelpHandler helpHandler;

    public HelpCommand(){
        helpHandler = new HelpHandler();
    }

    //命令执行方法,将调用请求接收者的业务方法
    public void execute() {
        helpHandler.display();
    }
}

Ele mantém uma referência ao destinatário da solicitação.

3. Crie um novo receptor de solicitação e ajude a classe de processamento de documentos

//帮助文档处理类:请求接受者
public class HelpHandler {
    public void display(){
        System.out.println("显示帮助文档");
    }
}

4. Crie uma nova classe de comando específica da mesma maneira: minimize a classe de comando

//最小化命令类:具体命令类
public class MinimizeCommand extends Command{

    //维持对请求接收者的引用
    private WindowHandler windowHandler;

    public MinimizeCommand(){
        windowHandler = new WindowHandler();
    }

    //命令执行方法,将调用请求接收者的业务方法
    public void execute() {
        windowHandler.minimize();
    }
}

Que mantém uma referência à classe de manipulação de janela minimizada do receptor da solicitação

5. Crie uma nova classe de processamento de janela minimizada

//窗口处理类:请求接收者
public class WindowHandler {
    public void minimize(){
        System.out.println("将窗口最小化");
    }
}

6. Novo remetente de solicitação: classe de chave de função

//功能键类:请求发送者
public class FunctionButton {
    //功能键名称
    private String name;
    //维持一个抽象命令对象的引用
    private Command command;

    public FunctionButton(String name) {
        this.name = name;
    }

    public String getName(){
        return this.name;
    }

    //为功能键注入命令
    public void setCommand(Command command){
        this.command = command;
    }

    public void onClick(){
        System.out.println("点击功能键:");
        command.execute();
    }
}

7. Crie uma nova tecla de função para definir a classe da janela

import java.util.ArrayList;

//功能键设置窗口类
public class FBSettingWindow {
    //窗口标题
    private String title;
    //定义一个ArrayList来存储所有功能键
    private ArrayList<FunctionButton> functionButtons = new ArrayList<FunctionButton>();

    public FBSettingWindow(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void addFunctionButton(FunctionButton fb){
        functionButtons.add(fb);
    }

    public void removeFunctionButton(FunctionButton fb){
        functionButtons.remove(fb);
    }

    //显示窗口及功能键
    public void display(){
        System.out.println("显示窗口:"+this.title);
        System.out.println("显示功能键:");
        for (Object obj : functionButtons) {
            System.out.println(((FunctionButton)obj).getName());
        }
        System.out.println("-------------------------");
    }
}

8. Método de chamada do cliente

public class Client {
    public static void main(String[] args) {
        FBSettingWindow fbsw = new FBSettingWindow("功能键设置");

        FunctionButton fb1,fb2;
        fb1 = new FunctionButton("功能键1");
        fb2 = new FunctionButton("功能键2");

        Command command1,command2;
        //通过读取配置文件或其它方式生成具体命令对象
        command1 = new HelpCommand();
        command2 = new MinimizeCommand();

        //将命令对象注入功能键
        fb1.setCommand(command1);
        fb2.setCommand(command2);

        fbsw.addFunctionButton(fb1);
        fbsw.addFunctionButton(fb2);
        fbsw.display();

        //调用功能键的业务方法
        fb1.onClick();
        fb2.onClick();

    }
}

9. Resumo

Se você precisar modificar a função da tecla de função, por exemplo, uma determinada tecla de função pode realizar "captura automática de tela", você só precisa adicionar uma nova classe de comando específica correspondentemente,

Crie um relacionamento de associação entre a classe de comando e o manipulador de tela (ScreenHandler) e, em seguida, injete o objeto da classe de comando específica em uma tecla de função por meio do arquivo de configuração.

O código original não precisa ser modificado e atende ao “princípio de abrir e fechar”. Neste processo, cada classe de comando específica corresponde a um processador de solicitação (receptor),

Ao injetar diferentes objetos de comando específicos no remetente da solicitação, o mesmo remetente pode corresponder a diferentes receptores, de modo a realizar "encapsular uma solicitação em um objeto,

Parametrize o cliente com diferentes solicitações", o cliente só precisa injetar o objeto de comando específico como parâmetro no remetente da solicitação, sem operar diretamente o receptor da solicitação.

As principais vantagens do padrão de comando:

(1) Reduza o grau de acoplamento do sistema. Como não há referência direta entre o solicitante e o destinatário, o solicitante e o destinatário estão completamente dissociados,

O mesmo solicitante pode corresponder a receptores diferentes, e o mesmo receptor também pode ser usado por solicitantes diferentes, e há uma boa independência entre os dois.

(2) Novos comandos podem ser facilmente adicionados ao sistema. Adicionar uma nova classe de comando específica é fácil porque adicionar uma nova classe de comando específica não afetará outras classes,

Não há necessidade de modificar o código-fonte do sistema original, ou mesmo o código da classe do cliente, para atender aos requisitos do “princípio de abertura e fechamento”.

(3) É relativamente fácil projetar uma fila de comandos ou comandos macro (comandos combinados).

(4) Fornecer um esquema de design e implementação para as operações de Desfazer e Refazer solicitadas.

As principais desvantagens do padrão Command são as seguintes:

Usar o padrão de comando pode fazer com que alguns sistemas tenham muitas classes de comandos concretas. Como uma classe de comando específica precisa ser projetada para cada operação de chamada para o receptor da solicitação,

Portanto, em alguns sistemas, pode ser necessário fornecer um grande número de classes de comandos específicas, o que afetará o uso do modo de comando.

Cena aplicável

Considere usar o padrão de comando quando:

(1) O sistema precisa dissociar o chamador e o receptor da solicitação para que o chamador e o destinatário não interajam diretamente. O chamador da solicitação não precisa saber da existência do destinatário, nem precisa saber quem é o destinatário,

O receptor também não precisa se preocupar quando é chamado.

(2) O sistema precisa especificar solicitações, enfileirar solicitações e executar solicitações em momentos diferentes. Um objeto de comando e o chamador original da solicitação podem ter tempos de vida diferentes,

Em outras palavras, o remetente da solicitação original pode não existir mais, mas o próprio objeto de comando ainda está ativo e o receptor da solicitação pode ser chamado por meio do objeto de comando,

Em vez de se preocupar com a existência do chamador da solicitação, ela pode ser implementada através de mecanismos como a solicitação de arquivos de log.

(3) O sistema precisa suportar as operações de comandos Desfazer e Refazer.

(4) O sistema precisa combinar um grupo de operações para formar um comando macro.

Acho que você gosta

Origin blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131973694
Recomendado
Clasificación