Exemple d'utilisation du mode conception-mode commande dans les touches de fonction personnalisées du programme Java-Desktop

Scènes

Pour développer une version de bureau de l'application, l'application fournit aux utilisateurs une série de touches de fonction personnalisées, les utilisateurs peuvent utiliser ces touches de fonction pour réaliser certaines opérations de raccourci.

Les utilisateurs peuvent lier les touches de fonction et les fonctions correspondantes, et peuvent également modifier le réglage des touches de fonction en fonction des besoins, et le système peut ajouter de nouvelles fonctions ou touches de fonction à l'avenir.

Ceci est possible si vous n'utilisez pas le modèle Command.

La classe de clé de fonction FunctionButton agit en tant qu'expéditeur de la demande et la classe de traitement du document d'aide HelpHandler agit en tant que destinataire de la demande, dans le onClick() de l'expéditeur FunctionButton.

La méthode appellera la méthode display() du récepteur HelpHandler.

Bouton de fonction :

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

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

Gestionnaire d'aide :

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

Problèmes avec ce qui précède :

(1) Puisqu'il existe un appel de méthode direct entre l'expéditeur de la requête et le destinataire de la requête, le degré de couplage est très élevé et le code source de l'expéditeur doit être modifié pour remplacer le destinataire de la requête.

Si vous devez remplacer le récepteur de requêtes HelpHandler par WindowHanlder (classe de gestion des fenêtres), vous devez modifier le code source de FunctionButton, ce qui viole le "principe d'ouverture et de fermeture".

(2) La fonction de la classe FunctionButton a été corrigée lors de la conception et de la mise en œuvre. Si un nouveau récepteur de requêtes est ajouté, si la classe FunctionButton d'origine n'est pas modifiée,

Ensuite, une nouvelle classe similaire à FunctionButton doit être ajoutée, ce qui entraînera une forte augmentation du nombre de classes dans le système.

Puisqu'il ne peut y avoir aucune relation entre le récepteur de requêtes HelpHandler, WindowHanlder et d'autres classes, ils n'ont pas de couche d'abstraction commune,

Par conséquent, il est également difficile de concevoir FunctionButton selon le « principe d’inversion de dépendance ».

(3) Les utilisateurs ne peuvent pas définir la fonction d'une touche de fonction en fonction de leurs propres besoins. Une fois la fonction d'une touche de fonction fixée, sa fonction ne peut pas être modifiée sans modifier le code source.

Le système manque de flexibilité.

Présentation du modèle de commande

Dans le développement logiciel, nous avons souvent besoin d'envoyer des requêtes à certains objets (appeler une ou plusieurs méthodes), mais nous ne savons pas qui est le destinataire de la requête.

Je ne sais pas quelle opération est demandée. À l'heure actuelle, nous espérons surtout concevoir des logiciels de manière faiblement couplée, afin que l'expéditeur et le destinataire de la demande

Il peut éliminer le couplage entre eux, rendre la relation d'appel entre les objets plus flexible et spécifier de manière flexible le destinataire de la requête et l'opération demandée.

Le mode commande offre une solution plus parfaite à ces problèmes.

Le mode commande peut complètement découpler l'expéditeur et le destinataire de la requête. Il n'y a pas de relation de référence directe entre l'expéditeur et le destinataire. L'objet qui envoie la requête a seulement besoin de savoir comment envoyer la requête.

sans avoir à savoir comment compléter la demande.

Modèle de commande :

Encapsuler une requête en tant qu'objet nous permet de paramétrer les clients avec différentes requêtes : de mettre en file d'attente les requêtes ou d'enregistrer les journaux de requêtes, et de prendre en charge les opérations annulables.

Le mode commande est un mode de comportement d'objet, son alias est le mode action (Action) ou le mode transaction (Transaction).

Diagramme de structure du mode commande

Les rôles inclus dans le mode commande :

Commande (classe de commande abstraite) :

La classe de commandes abstraites est généralement une classe ou une interface abstraite, dans laquelle des méthodes telles que execute() pour exécuter des requêtes sont déclarées,

Grâce à ces méthodes, les opérations associées du destinataire de la requête peuvent être invoquées.

ConcreteCommand (classe de commande spécifique) :

La classe de commandes concrètes est une sous-classe de la classe de commandes abstraites, qui implémente les méthodes déclarées dans la classe de commandes abstraites, et elle correspond à l'objet récepteur spécifique.

Liez-y les actions de l’objet récepteur. Lors de l'implémentation de la méthodeexecute(), l'opération (Action) correspondante de l'objet récepteur sera appelée.

Invoquant (appelant) :

L'appelant est l'expéditeur de la requête et il exécute la requête via l'objet de commande. Un appelant n'a pas besoin de déterminer son destinataire au moment de la conception,

Elle n’est donc associée qu’à la classe de commandes abstraites. Un objet de commande spécifique peut être injecté dans le programme lors de son exécution,

Appelez ensuite la méthodeexecute() de l'objet de commande spécifique, afin de réaliser les opérations associées du récepteur d'appel indirect.

Destinataire:

Le récepteur effectue des opérations liées à la demande et met en œuvre le traitement métier de la demande. L'essence du mode commande est d'encapsuler la requête,

Une requête correspond à une commande, séparant la responsabilité d'émettre la commande de la responsabilité d'exécuter la commande. Chaque commande est une opération :

La partie requérante envoie une demande pour effectuer une opération ; la partie réceptrice reçoit la demande et effectue l'opération correspondante.

Le mode commande permet au demandeur et au destinataire d'être indépendants, de sorte que le demandeur n'a pas besoin de connaître l'interface du destinataire,

Il n’est pas nécessaire de savoir comment la demande est reçue, si l’opération est effectuée, quand et comment elle est effectuée.

Note:

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

accomplir

Utilisez le mode commande pour implémenter les touches de fonction définies par l'utilisateur ci-dessus.

1. Créez une nouvelle classe de commandes abstraites

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

2. Créez une nouvelle classe de commande spécifique : classe de commande help

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

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

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

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

Il conserve une référence au destinataire de la demande.

3. Créez un nouveau récepteur de requêtes et aidez la classe de traitement des documents

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

4. Créez une nouvelle classe de commandes spécifique de la même manière : réduisez la classe de commandes

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

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

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

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

Qui maintient une référence à la classe de gestion de fenêtre minimisée du destinataire de la requête

5. Créez une nouvelle classe de traitement de fenêtre réduite

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

6. Nouvel expéditeur de requête : classe de clé de fonction

//功能键类:请求发送者
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. Créez une nouvelle touche de fonction pour définir la classe de fenêtre

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éthode d'appel du client

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. Résumé

Si vous devez modifier la fonction de la touche de fonction, par exemple, une certaine touche de fonction peut réaliser une "capture d'écran automatique", il vous suffit d'ajouter une nouvelle classe de commande spécifique en conséquence,

Créez une relation d'association entre la classe de commande et le gestionnaire d'écran (ScreenHandler), puis injectez l'objet de la classe de commande spécifique dans une touche de fonction via le fichier de configuration.

Le code original n'a pas besoin d'être modifié et est conforme au « principe d'ouverture et de fermeture ». Dans ce processus, chaque classe de commandes spécifique correspond à un processeur de requêtes (récepteur),

En injectant différents objets de commande spécifiques dans l'émetteur de la requête, ce même expéditeur peut correspondre à différents récepteurs, de manière à réaliser « l'encapsulation d'une requête dans un objet »,

Paramétrer le client avec différentes requêtes", le client n'a qu'à injecter l'objet de commande spécifique en tant que paramètre dans l'expéditeur de la requête, sans actionner directement le récepteur de la requête.

Les principaux avantages du modèle de commande :

(1) Réduisez le degré de couplage du système. Puisqu’il n’y a pas de référence directe entre le demandeur et le récepteur, le demandeur et le récepteur sont complètement découplés,

Un même demandeur peut correspondre à différents récepteurs, et un même récepteur peut également être utilisé par différents demandeurs, et il existe une bonne indépendance entre les deux.

(2) De nouvelles commandes peuvent être facilement ajoutées au système. L'ajout d'une nouvelle classe de commandes spécifique est simple car l'ajout d'une nouvelle classe de commandes spécifique n'affectera pas les autres classes,

Il n'est pas nécessaire de modifier le code source du système d'origine, ni même le code de la classe client, pour répondre aux exigences du « principe d'ouverture et de fermeture ».

(3) Il est relativement facile de concevoir une file d'attente de commandes ou une macro-commande (commande combinée).

(4) Fournir un schéma de conception et de mise en œuvre pour les opérations d'annulation et de rétablissement demandées.

Les principaux inconvénients du modèle Command sont les suivants :

L'utilisation du modèle de commande peut conduire à ce que certains systèmes aient trop de classes de commandes concrètes. Étant donné qu'une classe de commandes spécifique doit être conçue pour chaque opération d'appel au destinataire de la demande,

Par conséquent, dans certains systèmes, il peut être nécessaire de fournir un grand nombre de classes de commandes spécifiques, ce qui affectera l'utilisation du mode commande.

Scène applicable

Pensez à utiliser le modèle de commande lorsque :

(1) Le système doit découpler l'appelant de la demande et le destinataire de la demande afin que l'appelant et le destinataire n'interagissent pas directement. L'appelant n'a pas besoin de connaître l'existence du destinataire, ni de savoir qui est le destinataire.

Le destinataire n'a pas non plus à se soucier du moment où il est appelé.

(2) Le système doit spécifier les demandes, mettre les demandes en file d'attente et exécuter les demandes à des moments différents. Un objet de commande et l'appelant d'origine de la requête peuvent avoir des durées de vie différentes,

En d'autres termes, l'expéditeur de la requête d'origine peut ne plus exister, mais l'objet de commande lui-même est toujours actif et le destinataire de la requête peut être appelé via l'objet de commande,

Au lieu de se soucier de l'existence de l'appelant de la requête, celle-ci peut être implémentée via des mécanismes tels que la demande de fichiers journaux.

(3) Le système doit prendre en charge les opérations Annuler et Rétablir des commandes.

(4) Le système doit combiner un groupe d'opérations pour former une macro-commande.

Je suppose que tu aimes

Origine blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131973694
conseillé
Classement