Sept modèles de conception courants en Java

1. Modèle de singleton

Le modèle singleton est l'un des modèles de conception les plus couramment utilisés en Java, qui garantit qu'il n'y a qu'une seule instance d'une classe et fournit un point d'accès global.

Le cœur de la réalisation du mode singleton est de privatiser le constructeur de la classe pour empêcher l'extérieur de créer des instances directement via le constructeur. Dans le même temps, une méthode ou une variable statique doit être fournie à l'intérieur de la classe pour obtenir la seule instance de la classe.

Voici une implémentation simple du modèle singleton :

public class Singleton {
    
    
    private static Singleton instance = null;

    // 私有构造方法
    private Singleton() {
    
    
    }

    // 静态方法,获取唯一实例
    public static Singleton getInstance() {
    
    
        if (instance == null) {
    
    
            instance = new Singleton();
        }
        return instance;
    }
}

2. Modèle d'usine

Factory Pattern (Factory Pattern) est un modèle de conception de création couramment utilisé en Java, qui fournit une méthode pour encapsuler le processus de création d'objets et peut créer différents types d'objets en fonction de différents paramètres.

Il existe trois implémentations courantes du modèle de fabrique : le modèle de fabrique simple, le modèle de méthode de fabrique et le modèle de fabrique abstraite. En prenant le modèle d'usine simple comme exemple, le processus de mise en œuvre est le suivant :

  1. Définissez une classe de produits abstraite :
public abstract class Product {
    
    
    public abstract void use();
}
  1. Définissez des catégories de produits spécifiques :
public class ProductA extends Product {
    
    
    @Override
    public void use() {
    
    
        System.out.println("使用产品A");
    }
}

public class ProductB extends Product {
    
    
    @Override
    public void use() {
    
    
        System.out.println("使用产品B");
    }
}
  1. Définissez la classe d'usine :
public class Factory {
    
    
    public static Product createProduct(String type) {
    
    
        if ("A".equals(type)) {
    
    
            return new ProductA();
        } else if ("B".equals(type)) {
    
    
            return new ProductB();
        } else {
    
    
            throw new IllegalArgumentException("无效的产品类型");
        }
    }
}
  1. Appelez la classe factory pour créer des produits :
Product productA = Factory.createProduct("A");
productA.use(); // 输出:使用产品A

Product productB = Factory.createProduct("B");
productB.use(); // 输出:使用产品B

Dans l'implémentation ci-dessus, AbstractProductil s'agit d'une classe de produit abstraite qui définit les attributs et méthodes de base du produit. ProductAet ProductBest la classe de produit concrète qui implémente les méthodes définies dans la classe de produit abstraite.

FactoryIl s'agit d'une classe de fabrique qui crée différents types d'objets produit en fonction de différents paramètres. FactoryLa méthode dans est statique, il n'est pas nécessaire de créer d'abord un objet de fabrique, puis d'appeler la méthode.

En utilisant le modèle d'usine, le processus de création d'objet peut être efficacement encapsulé, réalisant l'idée de conception d'une cohésion élevée et d'un couplage faible, et facilitant la maintenance et l'extension du code.

3. Modèle d'usine abstrait

Le modèle d'usine abstrait (Abstract Factory Pattern) est un modèle de conception de création couramment utilisé en Java, qui fournit un moyen de créer une série d'interfaces d'objets liées ou interdépendantes sans spécifier leurs classes spécifiques.

Le modèle d'usine abstrait est similaire au modèle de méthode d'usine, sauf que la classe d'usine dans le modèle d'usine abstrait ne produit pas un seul produit, mais produit une série de produits liés.

Voici une simple implémentation de modèle de fabrique abstraite :

  1. Définissez une classe de produits abstraite :
public interface AbstractProductA {
    
    
    void use();
}

public interface AbstractProductB {
    
    
    void consume();
}
  1. Définissez des catégories de produits spécifiques :
public class ProductA1 implements AbstractProductA {
    
    
    @Override
    public void use() {
    
    
        System.out.println("使用ProductA1");
    }
}

public class ProductA2 implements AbstractProductA {
    
    
    @Override
    public void use() {
    
    
        System.out.println("使用ProductA2");
    }
}

public class ProductB1 implements AbstractProductB {
    
    
    @Override
    public void consume() {
    
    
        System.out.println("消费ProductB1");
    }
}

public class ProductB2 implements AbstractProductB {
    
    
    @Override
    public void consume() {
    
    
        System.out.println("消费ProductB2");
    }
}
  1. Définissez une classe de fabrique abstraite :
public interface AbstractFactory {
    
    
    AbstractProductA createProductA();

    AbstractProductB createProductB();
}
  1. Définissez une classe de fabrique concrète :
public class Factory1 implements AbstractFactory {
    
    
    @Override
    public AbstractProductA createProductA() {
    
    
        return new ProductA1();
    }

    @Override
    public AbstractProductB createProductB() {
    
    
        return new ProductB1();
    }
}

public class Factory2 implements AbstractFactory {
    
    
    @Override
    public AbstractProductA createProductA() {
    
    
        return new ProductA2();
    }

    @Override
    public AbstractProductB createProductB() {
    
    
        return new ProductB2();
    }
}
  1. Appelez la fabrique abstraite pour générer des produits :
AbstractFactory factory1 = new Factory1();
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
productA1.use(); // 输出:使用ProductA1
productB1.consume(); // 输出:消费ProductB1

AbstractFactory factory2 = new Factory2();
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
productA2.use(); // 输出:使用ProductA2
productB2.consume(); // 输出:消费ProductB2

Ce qui précède est une simple implémentation de modèle de fabrique abstraite. Parmi elles, la classe abstract factory AbstractFactorydéfinit des méthodes abstraites createProductA()et createProductB(), utilisées pour créer AbstractProductAet AbstractProductBtyper des objets.

La classe fabrique concrète implémente respectivement l'interface Factory1et implémente les deux méthodes abstraites définies dans l'interface pour produire des objets de type , et , respectivement.Factory2AbstractFactoryProductA1ProductB1ProductA2ProductB2

En utilisant le modèle d'usine abstraite, une série de produits connexes peut être générée de manière plus flexible. Il peut isoler le processus d'instanciation de la classe, et les objets créés par le client à l'aide de la fabrique abstraite sont une série de produits connexes sans se soucier de l'implémentation spécifique.

4. Modèle de constructeur

Builder Pattern (Builder Pattern) est un modèle de conception de création couramment utilisé en Java, qui sépare le processus de construction et la représentation d'un objet complexe, de sorte que le même processus de construction peut créer différentes représentations.

Le patron constructeur est principalement composé de 4 parties : constructeur abstrait, constructeur concret, réalisateur et produit. Parmi eux, le constructeur abstrait et le constructeur concret sont utilisés pour définir et réaliser le processus de création du produit, le commandant coordonne le constructeur pour construire le produit, et le produit est l'objet construit final.

Voici une implémentation simple du modèle de générateur :

  1. Définissez la classe de produit :
public class Product {
    
    
    private String partA;
    private String partB;
    private String partC;

    public String getPartA() {
    
    
        return partA;
    }

    public void setPartA(String partA) {
    
    
        this.partA = partA;
    }

    public String getPartB() {
    
    
        return partB;
    }

    public void setPartB(String partB) {
    
    
        this.partB = partB;
    }

    public String getPartC() {
    
    
        return partC;
    }

    public void setPartC(String partC) {
    
    
        this.partC = partC;
    }

    @Override
    public String toString() {
    
    
        return "Product{" +
                "partA='" + partA + '\'' +
                ", partB='" + partB + '\'' +
                ", partC='" + partC + '\'' +
                '}';
    }
}
  1. Définissez une classe de générateur abstraite :
public abstract class Builder {
    
    
    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public abstract Product getResult();
}
  1. Définissez une classe de constructeur en béton :
public class ConcreteBuilder extends Builder {
    
    
    private Product product = new Product();

    @Override
    public void buildPartA() {
    
    
        product.setPartA("PartA");
    }

    @Override
    public void buildPartB() {
    
    
        product.setPartB("PartB");
    }

    @Override
    public void buildPartC() {
    
    
        product.setPartC("PartC");
    }

    @Override
    public Product getResult() {
    
    
        return product;
    }
}
  1. Définissez la classe de conducteur :
public class Director {
    
    
    private Builder builder;

    public Director(Builder builder) {
    
    
        this.builder = builder;
    }

    public void construct() {
    
    
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}
  1. Créer un produit :
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
System.out.println(product);

Dans l'implémentation ci-dessus, Productil s'agit d'une classe de produits avec plusieurs attributs, qui peuvent être acquis et définis via des accesseurs et des modificateurs.

BuilderEst une classe de constructeur abstraite qui définit la méthode de construction du produit. La classe de générateur spécifique ConcreteBuilderimplémente toutes les méthodes de l'interface du générateur et implémente le processus de création de produits. DirectorC'est une classe de commandant chargée de contrôler l'avancement de l'ensemble du processus de construction.

Enfin, le produit est créé via le modèle de générateur. Le commandant confie le processus de construction spécifique au constructeur, et le constructeur crée différents produits en fonction des informations spécifiques fournies par le commandant. En utilisant le modèle de construction, les produits avec des structures complexes peuvent être construits de manière flexible.

5. Modèle de stratégie

Le modèle de stratégie (Strategy Pattern) est un modèle de conception comportemental couramment utilisé en Java. Il définit une série d'algorithmes, encapsule chaque algorithme et les rend interchangeables, permettant à l'algorithme de changer indépendamment du client qui l'utilise. .

Le modèle de stratégie se compose principalement de trois parties : interface de stratégie, classe de stratégie concrète et classe de contexte. L'interface de stratégie définit l'interface unifiée de l'algorithme, la classe de stratégie spécifique implémente l'algorithme défini dans l'interface de stratégie et la classe de contexte contient une référence à l'interface de stratégie et est responsable de l'appel de l'algorithme dans la classe de stratégie spécifique.

Voici une implémentation simple du modèle de stratégie :

  1. Définissez l'interface de la stratégie :
public interface Strategy {
    
    
    void execute();
}
  1. Définissez une classe de stratégie concrète :
public class StrategyA implements Strategy {
    
    
    @Override
    public void execute() {
    
    
        System.out.println("执行策略A");
    }
}

public class StrategyB implements Strategy {
    
    
    @Override
    public void execute() {
    
    
        System.out.println("执行策略B");
    }
}
  1. Définissez la classe de contexte :
public class Context {
    
    
    private Strategy strategy;

    public Context(Strategy strategy) {
    
    
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
    
    
        this.strategy = strategy;
    }

    public void doStrategy() {
    
    
        strategy.execute();
    }
}
  1. Utilisez le modèle de stratégie :
Strategy strategyA = new StrategyA();
Context context = new Context(strategyA);
context.doStrategy(); // 输出:执行策略A

Strategy strategyB = new StrategyB();
context.setStrategy(strategyB);
context.doStrategy(); // 输出:执行策略B

Dans l'implémentation ci-dessus, Strategyil s'agit d'une interface de stratégie abstraite, qui définit l'interface unifiée de l'algorithme. La classe de stratégie spécifique StrategyAimplémente StrategyBl'algorithme dans l'interface de stratégie et fournit une implémentation d'algorithme spécifique pour le modèle de stratégie.

ContextEst une classe de contexte qui contient une référence à une interface de stratégie et est utilisée pour appeler l'algorithme dans la classe de stratégie concrète. Grâce setStrategy()à la méthode, la stratégie peut être modifiée dynamiquement pour obtenir différents comportements.

6. Motif de décorateur

Decorator Pattern (Decorator Pattern) est un modèle de conception structurel permettant d'ajouter dynamiquement un comportement supplémentaire à un objet sans modifier la classe d'origine.

Dans ce mode, une classe de décorateur et une classe de composant sont définies. L'objet décoré fait référence à l'objet d'instance de la classe de composant et à ses sous-classes. La classe de décorateur et l'objet décoré ont la même classe parent, c'est-à-dire la classe de décorateur et Les objets décorés sont réalisés en implémentant la même interface ou en héritant de la même classe abstraite.

Lorsqu'elle est implémentée, la classe décorateur contient une variable membre de l'objet décoré et maintient une référence à l'objet décoré. Lors de l'appel de la méthode de l'objet décoré dans la classe décorateur, de nouvelles fonctions peuvent également être ajoutées.

Voici un exemple de code de modèle de décorateur simple :

// 抽象组件
interface Component {
    
    
    void operation();
}
 
// 具体组件
class ConcreteComponent implements Component {
    
    
    public void operation() {
    
    
        System.out.println("基础操作");
    }
}

// 抽象装饰器
class Decorator implements Component {
    
    
    protected Component component;
 
    public Decorator(Component component) {
    
    
        this.component = component;
    }
 
    public void operation() {
    
    
        component.operation();
    }
}
 
// 具体装饰器
class ConcreteDecorator extends Decorator {
    
    
    public ConcreteDecorator(Component component) {
    
    
        super(component);
    }
 
    public void operation() {
    
    
        super.operation();
        addedBehavior();
    }
 
    public void addedBehavior() {
    
    
        System.out.println("添加额外的行为");
    }
}

Dans le code ci-dessus, Componentc'est l'interface abstraite de l'objet décoré, et ConcreteComponentc'est l'objet décoré spécifique. Dans Decorator, l'objet à décorer est transmis pour initialisation et operation()la méthode est remplacée. Plutôt,ConcreteDecorator des décorateurs concrets qui héritent Decoratoret étendent le comportement de l'objet décoré.

Voici un exemple de code pour tester le décorateur :

Component component = new ConcreteComponent(); // 创建被装饰对象
component.operation(); // 调用基础操作
 
Decorator decorator = new ConcreteDecorator(component); // 使用被装饰对象进行初始化
decorator.operation(); // 调用装饰器的操作方法,同时也会执行被装饰对象的操作方法和新添加的行为

Lors de l'exécution, nous pouvons voir la sortie suivante :

基础操作
基础操作
添加额外的行为

Cela indique que l'opération a été transmise avec succès à l'objet decoree et que le décorateur concret a ajouté un comportement supplémentaire.

7. Modèle d'adaptateur

Adapter Pattern (Adapter Pattern) est un modèle de conception structurelle, utilisé pour convertir l'interface d'une classe existante dans la forme d'interface requise.

Le but du modèle d'adaptateur est de permettre aux classes avec des interfaces incompatibles de coopérer de manière transparente. Dans le modèle d'adaptateur, un adaptateur adapte l'interface d'une classe à l'interface d'une autre classe.

Il existe deux manières d'implémenter des adaptateurs : les adaptateurs d'objet et les adaptateurs de classe.

  • Adaptateur d'objet : l'adaptateur contient une référence à l'objet d'origine, "mariant" ainsi sa propre interface avec l'interface de l'objet d'origine.
  • Adaptateur de classe : l'adaptateur implémente l'héritage multiple pour convertir l'interface d'une classe dans la forme d'interface attendue par une autre classe.

Voici un exemple de code de modèle d'adaptateur simple :

  • Adaptateur d'objet :

    // 原始接口
    interface Shape {
          
          
        void draw();
    }
    
    // 原始类
    class Rectangle implements Shape {
          
          
        public void draw() {
          
          
            System.out.println("Rectangle draw()");
        }
    }
    
    // 适配器类
    class ObjectAdapter implements Shape {
          
          
        private Rectangle rectangle;
    
        public ObjectAdapter(Rectangle rectangle) {
          
          
            this.rectangle = rectangle;
        }
    
        public void draw() {
          
          
            rectangle.draw();
        }
    }
    
    // 测试代码
    public class ObjectAdapterTest {
          
          
        public static void main(String[] args) {
          
          
            Rectangle rectangle = new Rectangle();
            Shape shape = new ObjectAdapter(rectangle);
            shape.draw();
        }
    }
    
  • adaptateur de classe :

    // 原始类
    class Rectangle {
          
          
        void draw() {
          
          
            System.out.println("Rectangle draw()");
        }
    }
    
    // 目标接口
    interface Shape {
          
          
        void draw();
    }
    
    // 适配器类
    class ClassAdapter extends Rectangle implements Shape {
          
          
        public void draw() {
          
          
            super.draw();
        }
    }
    
    // 测试代码
    public class ClassAdapterTest {
          
          
        public static void main(String[] args) {
          
          
            Shape shape = new ClassAdapter();
            shape.draw();
        }
    }
    

Dans le code ci-dessus, nous avons un objet primitif Rectanglequi implémente Shapel'interface. Dans le pattern Object Adapter, nous créons un adaptateur ObjectAdapterpour convertir cet objet primitif en Shapeune interface. Dans le modèle d'adaptateur de classe, nous convertissons Rectangleles classes en Shapeinterfaces via l'héritage multiple. Dans le code de test, nous pouvons voir l'utilisation de l'adaptateur, passer l'objet adaptateur au code client et appeler la méthode correspondante.

Dans l'ensemble, le modèle d'adaptateur est un modèle de conception efficace qui peut nous aider à résoudre le problème d'incompatibilité d'interface, afin que différentes classes puissent coopérer les unes avec les autres pour accomplir des tâches.

8. Modèle d'observateur

Observer Pattern (Observer Pattern) est un modèle de conception comportemental, également appelé modèle de publication-abonnement, qui définit une relation de dépendance un à plusieurs entre les objets, de sorte que lorsqu'un objet change d'état, tous les objets qui en dépendent peuvent être avertis. et automatiquement mis à jour.

Dans le pattern Observateur, il existe deux types d'objets : Observateur et Sujet (ou Observé). Les observateurs s'enregistrent auprès du sujet pour recevoir des notifications lorsque l'état du sujet change. Un sujet maintient un ensemble d'observateurs et les avertit lorsque son état change. Les sujets les notifient des changements d'état en appelant l'interface uniforme des observateurs.

Voici un exemple de code de modèle d'observateur simple :

// 观察者接口
interface Observer {
    
    
    void update(String message);
}
 
// 具体观察者1
class ConcreteObserver1 implements Observer {
    
    
    @Override
    public void update(String message) {
    
    
        System.out.println("ConcreteObserver1:" + message);
    }
}
 
// 具体观察者2
class ConcreteObserver2 implements Observer {
    
    
    @Override
    public void update(String message) {
    
    
        System.out.println("ConcreteObserver2:" + message);
    }
}
 
// 主题接口
interface Subject {
    
    
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObserver(String message);
}
 
// 具体主题
class ConcreteSubject implements Subject {
    
    
    private List<Observer> list = new ArrayList<>();
 
    // 注册观察者
    public void registerObserver(Observer observer) {
    
    
        list.add(observer);
    }
 
    // 移除观察者
    public void removeObserver(Observer observer) {
    
    
        list.remove(observer);
    }
 
    // 通知观察者
    public void notifyObserver(String message) {
    
    
        for (Observer observer : list) {
    
    
            observer.update(message);
        }
    }
}

Dans le code ci-dessus, nous avons l'interface Observer Observeret l'implémentation concrète de deux Observers ConcreteObserver1et ConcreteObserver2. Il y a aussi l'interface de sujet Subject, qui a trois méthodes : registerObserver, , removeObserveret notifyObserver, qui sont utilisées pour enregistrer des observateurs, supprimer des observateurs et notifier des observateurs. Enfin, nous avons un sujet concret ConcreteSubjectqui maintient Observerune liste d'objets, implémentant Subjectles trois méthodes dans l'interface.

Voici un exemple de code utilisant le modèle d'observateur Java :

public class ObserverTest {
    
    
    public static void main(String[] args) {
    
    
        ConcreteSubject subject = new ConcreteSubject(); // 创建具体主题
        Observer observer1 = new ConcreteObserver1(); // 创建具体观察者1
        Observer observer2 = new ConcreteObserver2(); // 创建具体观察者2
        subject.registerObserver(observer1); // 注册观察者1
        subject.registerObserver(observer2); // 注册观察者2
        subject.notifyObserver("观察者模式测试"); // 通知所有观察者
    }
}

Dans le code de test, nous avons créé un sujet concret ConcreteSubjectet deux observateurs concrets ConcreteObserver1et ConcreteObserver2. Leur comportement doit être appelé après que l'état du sujet a changé. Nous enregistrons ces deux observateurs et utilisons notifyObserver()la méthode pour les notifier que l'état du sujet a changé.

En mode observateur, la séparation du sujet et de l'observateur rend le code plus lâchement couplé, permettant une interaction et une collaboration plus flexibles entre les objets.

Guess you like

Origin blog.csdn.net/qq_45196093/article/details/130392953