Sieben gängige Entwurfsmuster in Java

1. Singleton-Muster

Das Singleton-Muster ist eines der am häufigsten verwendeten Entwurfsmuster in Java, das sicherstellt, dass es nur eine Instanz einer Klasse gibt und einen globalen Zugriffspunkt bereitstellt.

Der Kern der Implementierung des Singleton-Modus besteht darin, den Konstruktor der Klasse zu privatisieren, um zu verhindern, dass Außenstehende Instanzen direkt über den Konstruktor erstellen. Gleichzeitig muss innerhalb der Klasse eine statische Methode oder Variable bereitgestellt werden, um die einzige Instanz der Klasse zu erhalten.

Das Folgende ist eine einfache Singleton-Musterimplementierung:

public class Singleton {
    
    
    private static Singleton instance = null;

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

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

2. Fabrikmuster

Factory Pattern (Factory Pattern) ist ein in Java häufig verwendetes Erstellungsentwurfsmuster, das eine Methode zum Kapseln des Prozesses der Objekterstellung bereitstellt und verschiedene Objekttypen gemäß unterschiedlichen Parametern erstellen kann.

Es gibt drei gängige Implementierungen des Factory-Musters: einfaches Factory-Muster, Factory-Methodenmuster und abstraktes Factory-Muster. Am Beispiel des einfachen Factory-Musters sieht der Implementierungsprozess wie folgt aus:

  1. Definieren Sie eine abstrakte Produktklasse:
public abstract class Product {
    
    
    public abstract void use();
}
  1. Definieren Sie bestimmte Produktkategorien:
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. Definieren Sie die Factory-Klasse:
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. Rufen Sie die Factory-Klasse auf, um Produkte zu erstellen:
Product productA = Factory.createProduct("A");
productA.use(); // 输出:使用产品A

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

In der obigen Implementierung AbstractProducthandelt es sich um eine abstrakte Produktklasse, die die grundlegenden Attribute und Methoden des Produkts definiert. ProductAund ProductBist die konkrete Produktklasse, die die in der abstrakten Produktklasse definierten Methoden implementiert.

FactoryEs handelt sich um eine Factory-Klasse, die verschiedene Arten von Produktobjekten gemäß unterschiedlichen Parametern erstellt. FactoryDie Methode in ist statisch. Es ist nicht erforderlich, zuerst ein Factory-Objekt zu erstellen und dann die Methode aufzurufen.

Durch die Verwendung des Factory-Musters kann der Objekterstellungsprozess effektiv gekapselt werden, wodurch die Entwurfsidee einer hohen Kohäsion und einer geringen Kopplung verwirklicht und die Wartung und Erweiterung des Codes erleichtert wird.

3. Abstraktes Fabrikmuster

Das Abstract Factory Pattern (Abstract Factory Pattern) ist ein in Java häufig verwendetes Erstellungsentwurfsmuster, das eine Möglichkeit bietet, eine Reihe verwandter oder voneinander abhängiger Objektschnittstellen zu erstellen, ohne deren spezifische Klassen anzugeben.

Das abstrakte Fabrikmuster ähnelt dem Fabrikmethodenmuster, mit der Ausnahme, dass die Fabrikklasse im abstrakten Fabrikmuster kein einzelnes Produkt, sondern eine Reihe verwandter Produkte erzeugt.

Das Folgende ist eine einfache abstrakte Factory-Musterimplementierung:

  1. Definieren Sie eine abstrakte Produktklasse:
public interface AbstractProductA {
    
    
    void use();
}

public interface AbstractProductB {
    
    
    void consume();
}
  1. Definieren Sie bestimmte Produktkategorien:
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. Definieren Sie eine abstrakte Factory-Klasse:
public interface AbstractFactory {
    
    
    AbstractProductA createProductA();

    AbstractProductB createProductB();
}
  1. Definieren Sie eine konkrete Factory-Klasse:
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. Rufen Sie die abstrakte Fabrik auf, um Produkte zu generieren:
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

Das Obige ist eine einfache abstrakte Factory-Musterimplementierung. Darunter AbstractFactorydefiniert die abstrakte Factory-Klasse abstrakte Methoden createProductA()und createProductB(), die zum Erstellen AbstractProductAund AbstractProductBTypisieren von Objekten verwendet werden.

Die konkrete Factory-Klasse implementiert jeweils die Schnittstelle Factory1und implementiert die beiden in der Schnittstelle definierten abstrakten Methoden, um Objekte vom Typ bzw. zu erzeugen.Factory2AbstractFactoryProductA1ProductB1ProductA2ProductB2

Durch die Verwendung des abstrakten Fabrikmusters kann eine Reihe verwandter Produkte flexibler generiert werden. Es kann den Instanziierungsprozess der Klasse isolieren, und die vom Client mithilfe der abstrakten Fabrik erstellten Objekte sind eine Reihe verwandter Produkte, ohne sich um die spezifische Implementierung zu kümmern.

4. Builder-Muster

Builder Pattern (Builder Pattern) ist ein in Java häufig verwendetes Erstellungsentwurfsmuster, das den Konstruktionsprozess und die Darstellung eines komplexen Objekts trennt, sodass mit demselben Konstruktionsprozess unterschiedliche Darstellungen erstellt werden können.

Das Builder-Muster besteht hauptsächlich aus 4 Teilen: abstrakter Builder, konkreter Builder, Regisseur und Produkt. Unter ihnen werden der abstrakte Builder und der konkrete Builder verwendet, um den Erstellungsprozess des Produkts zu definieren und zu realisieren, der Kommandant koordiniert den Builder, um das Produkt zu bauen, und das Produkt ist das endgültige gebaute Objekt.

Hier ist eine einfache Builder-Musterimplementierung:

  1. Definieren Sie die Produktklasse:
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. Definieren Sie eine abstrakte Builder-Klasse:
public abstract class Builder {
    
    
    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public abstract Product getResult();
}
  1. Definieren Sie eine konkrete Builder-Klasse:
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. Definieren Sie die Leiterklasse:
public class Director {
    
    
    private Builder builder;

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

    public void construct() {
    
    
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}
  1. Erstellen Sie ein Produkt:
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
director.construct();
Product product = builder.getResult();
System.out.println(product);

In der obigen Implementierung Producthandelt es sich um eine Produktklasse mit mehreren Attributen, die über Accessoren und Modifikatoren erfasst und festgelegt werden können.

BuilderIst eine abstrakte Builder-Klasse, die die Konstruktionsmethode des Produkts definiert. Die spezifische Builder-Klasse ConcreteBuilderimplementiert alle Methoden in der Builder-Schnittstelle und implementiert den Prozess der Produkterstellung. DirectorEs handelt sich um eine Kommandantenklasse, die für die Kontrolle des Fortschritts des gesamten Bauprozesses verantwortlich ist.

Schließlich wird das Produkt durch das Builder-Muster erstellt. Der Kommandant vertraut dem Bauunternehmer den spezifischen Bauprozess an, und der Bauunternehmer erstellt verschiedene Produkte gemäß den spezifischen Informationen des Kommandanten. Durch die Verwendung des Builder-Musters können Produkte mit komplexen Strukturen flexibel gebaut werden.

5. Strategiemuster

Strategiemuster (Strategiemuster) ist ein Verhaltensentwurfsmuster, das häufig in Java verwendet wird. Es definiert eine Reihe von Algorithmen, kapselt jeden Algorithmus und macht sie austauschbar, sodass sich der Algorithmus unabhängig vom Client ändern kann, der ihn verwendet.

Das Strategiemuster besteht hauptsächlich aus drei Teilen: Strategieschnittstelle, konkrete Strategieklasse und Kontextklasse. Die Strategieschnittstelle definiert die einheitliche Schnittstelle des Algorithmus, die spezifische Strategieklasse implementiert den in der Strategieschnittstelle definierten Algorithmus und die Kontextklasse enthält einen Verweis auf die Strategieschnittstelle und ist für den Aufruf des Algorithmus in der spezifischen Strategieklasse verantwortlich.

Hier ist eine einfache Implementierung eines Strategiemusters:

  1. Definieren Sie die Strategieschnittstelle:
public interface Strategy {
    
    
    void execute();
}
  1. Definieren Sie eine konkrete Strategieklasse:
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. Definieren Sie die Kontextklasse:
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. Verwenden Sie das Strategiemuster:
Strategy strategyA = new StrategyA();
Context context = new Context(strategyA);
context.doStrategy(); // 输出:执行策略A

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

In der obigen Implementierung Strategyhandelt es sich um eine abstrakte Strategieschnittstelle, die die einheitliche Schnittstelle des Algorithmus definiert. Die spezifische Strategieklasse StrategyAimplementiert StrategyBden Algorithmus in der Strategieschnittstelle und stellt eine spezifische Algorithmusimplementierung für das Strategiemuster bereit.

ContextIst eine Kontextklasse, die einen Verweis auf eine Strategieschnittstelle enthält und zum Aufrufen des Algorithmus in der konkreten Strategieklasse verwendet wird. Durch setStrategy()die Methode kann die Strategie dynamisch geändert werden, um unterschiedliche Verhaltensweisen zu erreichen.

6. Dekorationsmuster

Decorator Pattern (Decorator Pattern) ist ein strukturelles Entwurfsmuster zum dynamischen Hinzufügen zusätzlicher Verhaltensweisen zu einem Objekt, ohne die ursprüngliche Klasse zu ändern.

In diesem Modus werden eine Dekoratorklasse und eine Komponentenklasse definiert. Das dekorierte Objekt bezieht sich auf das Instanzobjekt der Komponentenklasse und ihrer Unterklassen. Die Dekoratorklasse und das dekorierte Objekt haben dieselbe übergeordnete Klasse, dh die Dekoratorklasse und Die dekorierten Objekte werden durch die Implementierung derselben Schnittstelle oder die Erbung derselben abstrakten Klasse realisiert.

Bei der Implementierung enthält die Dekoratorklasse eine Mitgliedsvariable des dekorierten Objekts und verwaltet einen Verweis auf das dekorierte Objekt. Beim Aufrufen der Methode des dekorierten Objekts in der Dekoratorklasse können auch einige neue Funktionen hinzugefügt werden.

Das Folgende ist ein einfacher Beispielcode für ein Dekorationsmuster:

// 抽象组件
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("添加额外的行为");
    }
}

Im obigen Code Componenthandelt es sich um die abstrakte Schnittstelle des dekorierten Objekts und ConcreteComponentum das spezifische dekorierte Objekt. In Decoratorwird das zu dekorierende Objekt zur Initialisierung übergeben und operation()die Methode überschrieben. Vielmehr handelt es sich um konkrete Dekorateure, die das Verhalten des zu dekorierenden Objekts ConcreteDecoratorübernehmen und erweitern.Decorator

Hier ist ein Beispielcode zum Testen des Dekorators:

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

Beim Ausführen können wir die folgende Ausgabe sehen:

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

Dies zeigt an, dass der Vorgang erfolgreich an das decoree-Objekt übergeben wurde und dass der konkrete Dekorateur zusätzliches Verhalten hinzugefügt hat.

7. Adaptermuster

Adaptermuster (Adaptermuster) ist ein strukturelles Entwurfsmuster, das verwendet wird, um die Schnittstelle einer vorhandenen Klasse in die erforderliche Schnittstellenform umzuwandeln.

Der Zweck des Adaptermusters besteht darin, Klassen mit inkompatiblen Schnittstellen eine nahtlose Zusammenarbeit zu ermöglichen. Im Adaptermuster passt ein Adapter die Schnittstelle einer Klasse an die Schnittstelle einer anderen Klasse an.

Es gibt zwei Möglichkeiten, Adapter zu implementieren: Objektadapter und Klassenadapter.

  • Objektadapter: Der Adapter enthält einen Verweis auf das Originalobjekt und „verheiratet“ so seine eigene Schnittstelle mit der Schnittstelle des Originalobjekts.
  • Klassenadapter: Der Adapter implementiert Mehrfachvererbung, um die Schnittstelle einer Klasse in die von einer anderen Klasse erwartete Schnittstellenform umzuwandeln.

Das Folgende ist ein einfacher Beispielcode für ein Adaptermuster:

  • Objektadapter:

    // 原始接口
    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();
        }
    }
    
  • Klassenadapter:

    // 原始类
    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();
        }
    }
    

Im obigen Code haben wir ein primitives Objekt , das die Schnittstelle Rectangleimplementiert . ShapeIm Objektadaptermuster erstellen wir einen Adapter, ObjectAdapterum dieses primitive Objekt in eine Schnittstelle umzuwandeln Shape. Im Klassenadaptermuster konvertieren wir RectangleKlassen Shapedurch Mehrfachvererbung in Schnittstellen. Im Testcode können wir die Verwendung des Adapters sehen, das Adapterobjekt an den Clientcode übergeben und die entsprechende Methode aufrufen.

Insgesamt ist das Adaptermuster ein effektives Entwurfsmuster, das uns dabei helfen kann, das Problem der Schnittstelleninkompatibilität zu bewältigen, sodass verschiedene Klassen bei der Erledigung von Aufgaben zusammenarbeiten können.

8. Beobachtermuster

Observer Pattern (Observer Pattern) ist ein Verhaltensentwurfsmuster, auch bekannt als Publish-Subscribe-Muster, das eine Eins-zu-Viele-Abhängigkeitsbeziehung zwischen Objekten definiert, sodass sich alle davon abhängigen Objekte ändern können, wenn sich der Status eines Objekts ändert Lassen Sie sich benachrichtigen und automatisch aktualisieren.

Im Observer-Muster gibt es zwei Arten von Objekten: Observer und Subject (oder Observed). Beobachter registrieren sich beim Subjekt, um Benachrichtigungen zu erhalten, wenn sich der Zustand des Subjekts ändert. Ein Subjekt unterhält eine Reihe von Beobachtern und benachrichtigt diese, wenn sich sein Zustand ändert. Subjekte benachrichtigen sie über Zustandsänderungen, indem sie die einheitliche Schnittstelle der Beobachter aufrufen.

Das Folgende ist ein einfacher Beispielcode für ein Beobachtermuster:

// 观察者接口
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);
        }
    }
}

Im obigen Code haben wir eine Observer-Schnittstelle Observerund eine konkrete Implementierung von zwei Observern ConcreteObserver1und ConcreteObserver2. Es gibt auch die Subjektschnittstelle Subject, die über drei Methoden verfügt: registerObserver, removeObserverund notifyObserver, mit denen Beobachter registriert, Beobachter entfernt und Beobachter benachrichtigt werden. Schließlich haben wir ein konkretes Subjekt ConcreteSubject, das eine Liste von Objekten verwaltet und die drei Methoden in der Schnittstelle Observerimplementiert .Subject

Das Folgende ist ein Beispielcode, der das Java-Beobachtermuster verwendet:

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("观察者模式测试"); // 通知所有观察者
    }
}

Im Testcode haben wir ein konkretes Subjekt ConcreteSubjectund zwei konkrete Beobachter erstellt ConcreteObserver1und ConcreteObserver2. Ihr Verhalten soll aufgerufen werden, nachdem sich der Themenstatus geändert hat. Wir registrieren diese beiden Beobachter und nutzen notifyObserver()die Methode, um sie darüber zu informieren, dass sich der Subjektstatus geändert hat.

Im Beobachtermodus wird der Code durch die Trennung von Subjekt und Beobachter lockerer gekoppelt, was eine flexiblere Interaktion und Zusammenarbeit zwischen Objekten ermöglicht.

Acho que você gosta

Origin blog.csdn.net/qq_45196093/article/details/130392953
Recomendado
Clasificación