Maison  >  Article  >  Java  >  Implémentation du modèle de stratégie dans les modèles de conception Java

Implémentation du modèle de stratégie dans les modèles de conception Java

王林
王林avant
2023-04-24 23:37:061877parcourir

1 Présentation

Dans le développement quotidien, nous rencontrons souvent une situation où il existe de nombreux algorithmes ou stratégies pour implémenter une fonction. Nous pouvons implémenter cette fonction en fonction de différents algorithmes ou stratégies. Par exemple : si vous souhaitez calculer une méthode de calcul logistique, toutes sont facturées. Différentes livraisons express ont différentes méthodes de facturation, telles que JD Express, Best Express et YTO Express. La façon dont ils calculent les frais d’expédition est différente. Alors comment y parvenir ? Les plus simples sont si...sinon...ou changer...cas.... Ces deux implémentations sont appelées codage en dur. S'il existe une nouvelle méthode de facturation comme Yunda Express, nous devons alors modifier le code source de notre algorithme. Cela rendra le code volumineux et difficile à maintenir.

Nous devons donc implémenter une manière dont chacun a son propre algorithme, et il nous suffit de choisir la méthode à appeler sur le client.

2 Strategy Pattern

2.1 Components

Classe d'environnement (Contexte) : configurée avec un objet ConcreteStrategy. Conservez une référence à l’objet Stratégie. Vous pouvez définir une interface pour permettre à Strategy d'accéder à ses données.

Classe de stratégie abstraite (Stratégie) : définit l'interface publique pour tous les algorithmes pris en charge. Context utilise cette interface pour appeler un algorithme défini par une ConcreteStrategy.

Classe Concrete Strategy (ConcreteStrategy) : implémente des algorithmes spécifiques avec l'interface Strategy.

2.2 Exemple de code

Prenons comme exemple les tarifs de fret de différentes sociétés de transport express :

Étape 1 : Définissez une classe de stratégie abstraite (méthode de facturation)

public interface CommandStrategy {
    /**
     * 计费方式
     * @param message
     */
    void calMoney(String message);
}

Étape 2 : Définissez une classe de stratégie spécifique (différentes classes d'algorithmes implémentent cela interface)

public class BaiShiCommand implements CommandStrategy {
    /**
     * 百世快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("百世快递收费方式:"+"起步20,每公斤6元");
    }
}
public class JingDongCommand implements CommandStrategy {
    /**
     * 京东快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("京东快递收费方式:"+"起步30,每公斤5元");
    }
}
public class YuanTongCommand implements CommandStrategy {
    /**
     * 圆通快递计费方式
     * @param message
     */
    @Override
    public void calMoney(String message) {
        System.out.println("圆通快递收费方式:"+"起步10,每公斤8元");
    }
}

Étape 3 : Définir la classe d'environnement

public class CommandContext {
    public CommandStrategy getInstance(String commandType) {
        CommandStrategy commandStrategy = null;
        Map<String, String> allClazz = CommandEnum.getAllClazz();
        //拿到对应算法类对应的路径
        String clazz = allClazz.get(commandType.trim().toLowerCase());
        if (StringUtils.isNotEmpty(clazz)) {
            try {
                try {
                    //创建一个对象实例
                    commandStrategy = (CommandStrategy) Class.forName(clazz).newInstance();//调用无参构造器创建实例
                } catch (InstantiationException | IllegalAccessException e) {
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        System.out.println("commandStrategy:"+commandStrategy);
        return commandStrategy;
    }
}

Définir une classe d'énumération :

public enum CommandEnum {
    JingDong("京东", "com.liubujun.design.command.JingDongCommand"), BaiShi("百世", "com.liubujun.design.command.BaishiCommand"), YuanTong("圆通", "com.liubujun.design.command.YuanTongCommand");
    private String name;
    private String clazz;
    public static Map<String, String> getAllClazz() {
        Map<String, String> map = new HashMap<>(8);
        System.out.println("==================="+Arrays.toString(CommandEnum.values())+"================");
        for (CommandEnum commandEnum : CommandEnum.values()) {
            map.put(commandEnum.getCommand(), commandEnum.getClazz());
        }
        return map;
    }
    public String getCommand() {
        return name;
    }
    CommandEnum(String command, String clazz) {
        this.name = command;
        this.clazz = clazz;
    }
    public void setCommand(String command) {
        this.name = command;
    }
    public String getClazz() {
        return clazz;
    }
    public void setClazz(String clazz) {
        this.clazz = clazz;
    }
}

Client :

public class MainStart {
    public static void main(String[] args) {
        String message = "京东";
        CommandContext commandContext = new CommandContext();
        //拿到message对应算法的对象实例
        CommandStrategy commandStrategy = commandContext.getInstance(message);
        commandStrategy.calMoney(message);
    }
}

De cette façon, le client peut appeler directement quelle méthode de facturation express

Implémentation du modèle de stratégie dans les modèles de conception Java

2.3 Avantage Inconvénients

Avantages :

1) Série d'algorithmes associés La hiérarchie de classes Strategy définit une série d'algorithmes ou de comportements réutilisables pour le contexte. L'héritage permet d'extraire les fonctionnalités communes de ces algorithmes.

2) Fournit un moyen de remplacer la relation d'héritage : l'héritage fournit un autre moyen de prendre en charge plusieurs algorithmes ou comportements. Vous pouvez directement sous-classer la classe Context pour lui donner un comportement différent. Mais cela codera en dur le comportement dans le contexte et mélangera l'implémentation de l'algorithme avec l'implémentation du contexte, ce qui rendra le contexte difficile à comprendre, à maintenir et à étendre, et il ne pourra pas modifier dynamiquement l'algorithme. Vous vous retrouvez avec un tas de classes liées, la seule différence entre elles est l'algorithme ou le comportement qu'elles utilisent. L'encapsulation de l'algorithme dans une classe de stratégie indépendante vous permet de le modifier indépendamment de son contexte, ce qui le rend facile à changer, à comprendre et à étendre.

3) Éliminez certaines instructions conditionnelles if else : le mode Stratégie offre une alternative à la sélection du comportement souhaité avec des instructions conditionnelles. Lorsque différents comportements sont empilés dans une classe, il est difficile d’éviter d’utiliser des instructions conditionnelles pour sélectionner le comportement approprié. L'encapsulation du comportement dans des classes de stratégie distinctes élimine ces instructions conditionnelles. Un code comportant de nombreuses instructions conditionnelles indique généralement la nécessité d'utiliser le mode Stratégie.

4) Choix d'implémentation Le mode Stratégie peut fournir différentes implémentations du même comportement. Les clients peuvent choisir parmi différentes stratégies basées sur différentes exigences de compromis temps/espace.

Inconvénients : 

1) Le client doit connaître toutes les classes de stratégie et décider quelle classe de stratégie utiliser : Ce modèle présente un inconvénient potentiel, c'est-à-dire que si un client souhaite choisir une stratégie appropriée, il doit savoir ce que sont ces stratégies. avoir. Quelle différence. À ce stade, des problèmes spécifiques de mise en œuvre devront peut-être être exposés au client. Par conséquent, le mode Stratégie n’est nécessaire que lorsque ces différentes variantes de comportement sont liées au comportement du client.

2) Surcharge de communication entre Stratégie et Contexte : Peu importe que l'algorithme implémenté par chaque ConcreteStrategy soit simple ou complexe, ils partagent tous l'interface définie par Strategy. Il est donc possible que certains ConcreteStrategy n'utilisent pas toutes les informations qui leur sont transmises via cette interface ; un simple ConcreteStrategy n'utilisera aucune des informations ! Cela signifie que parfois le Context créera et initialisera des paramètres qui ne seront jamais utilisés. Si un tel problème existe, un couplage plus étroit entre stratégie et contexte sera nécessaire.

3) Le modèle de stratégie entraînera la génération de nombreuses classes de stratégie : le nombre d'objets peut être réduit dans une certaine mesure en utilisant le modèle de poids mouche. La stratégie d'augmentation du nombre d'objets augmente le nombre d'objets dans une application. Parfois, vous pouvez réduire cette surcharge en implémentant la stratégie en tant qu'objet sans état pouvant être partagé par différents contextes. Tout état restant est maintenu par le contexte. Le contexte transmet cet état à chaque requête adressée à l'objet Strategy. Une stratégie partagée ne doit pas maintenir l’état entre les appels.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer