Quick start tutorials for 23 common design patterns

I. Introduction

Further reading

Illustration of common design patterns UML

Common 23 design patterns Java classic implementation (use common e-commerce business orders, shopping carts, merchants, payments, coupons as examples)

Quick start tutorial for 23 common design patterns for JavaScript versions

1. Design pattern definition

Design patterns are a set of useful solutions to specific types of software design problems. They often provide an abstracted way to express solutions to common problems in an application, helping developers solve problems more effectively. The purpose of design patterns is to help developers solve software design problems, improve development efficiency, reduce development costs, improve code quality and maintainability, and better manage and understand complex systems. The advantages of design patterns are that they can improve code maintainability, reduce code duplication, improve development efficiency, reduce development costs, improve code quality and maintainability, and better manage and understand complex systems. The disadvantage of design patterns is that they can complicate the code or over-engineer. The origin of design patterns was proposed by GoF (Gang of Four) in his 1995 book Design Patterns: Foundations of Reusable Object-Oriented Software.

2. The history of design patterns

Design patterns date back to the 1960s, when prominent software engineers and designers began to study how to improve the efficiency and maintainability of software development. They found that applying some recurring design patterns can increase the efficiency of software development and greatly improve the readability and maintainability of the software. These design patterns became known as "timeless design patterns" in the late 1970s and were published in 1995 by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Their book, "Design Patterns: Foundations of Reusable Object-Oriented Software," became a representative work of design patterns and sparked a lively discussion about them. In addition, the book provides software developers with a set of reusable design patterns to help them better understand and implement design patterns

Second, the six principles of design patterns

General principle: Open Close Principle

Entities should be open to extensions and closed to modifications, i.e. software entities should try to extend without modifying the original code.

The point of attention in application is to make full use of abstract classes, interfaces, polymorphism and other characteristics, encapsulate the variable part, and improve the flexibility and maintainability of the system.

1. The principle of single responsibility

A class should be responsible for only one responsibility, and there should be no class changes caused by more than one non-responsibility reason. Simply put, the responsibility of the class should be single.

The point of attention when applying is to divide the responsibilities of the class as clearly as possible during the design, modularize the function, and improve the flexibility and maintainability of the system.

2 Liskov Substitution Principle

Liskov Substitution Principle LSP One of the basic principles of object-oriented design. The Richter substitution principle states that where any base class can appear, subclasses must appear. LSP is the cornerstone of inheritance reuse, only when the derived class can replace the base class, the function of the software unit is not affected, the base class can be truly reused, and the derived class can also add new behavior on the basis of the base class. The Richter substitution principle complements the "open-close" principle. The key step in implementing the "open-close" principle is abstraction. The inheritance relationship between the base class and the subclass is the concrete implementation of abstraction, so the principle of Richter substitution is a specification of the specific steps to achieve abstraction.

In the history substitution principle, the methods of the parent class of the child class should not be overridden and overloaded as much as possible. Because the parent class represents a defined structure and interacts with the outside world through the interface of this specification, the child class should not break it casually.

The point of application is that there should be a common abstraction layer between parent and child classes at design time so that child classes can override the abstract methods of the parent class and implement those abstract methods in the child class.

3. Dependence Inversion Principle

This is the basis of the open-close principle, concrete content: interface-oriented programming, relying on abstraction rather than concrete.

The point of application is to base the design on the basis of abstraction, and try to reduce the level of detail so that the system can respond more flexibly to changes. When writing code with a concrete class, it does not interact with the concrete class, but with the upper-level interface of the concrete class.

4. Interface Segregation Principle

There are no subclasses in each interface that are not used but must be implemented, otherwise the interface must be split. It is better to use multiple isolated interfaces than to use a single interface (an interface in which multiple interface methods are grouped into one). Simply put, use multiple specialized interfaces instead of a single overall interface.

The point of attention when applying is to decompose the interface and use multiple small interfaces to better realize the modular management of functions and improve the flexibility and maintainability of the system.

5 Demeter Principle

That is: the less a class knows about the classes it depends on, the better. That is, no matter how complex the dependent class is, the logic should be encapsulated inside the method and provided to the outside through the public method. This way, when the dependent class changes, it can have minimal impact on the class.

Another expression of the principle of least knowledge is to communicate only with direct friends. As long as there is a coupling relationship between classes, it is called a friend relationship. Coupling is divided into dependency, association, aggregation, combination, and so on. We call classes that appear in member variables, method parameters, and method return values direct friends. Local variables and temporary variables are not direct friends. We ask that unfamiliar classes do not appear as local variables in the class.

The point of application is to minimize the coupling between classes and improve the flexibility and maintainability of the system.

6, Composite Reuse Principle

It refers to the use of composition/aggregation as much as possible, rather than using inheritance relationships to achieve the purpose of reuse.

When applying, pay attention to the use of composition/aggregation as much as possible, the coupling that may be brought by inheritance is too strong, thus affecting the flexibility and maintainability of the system.

Second, the classification of design patterns

In general, design patterns fall into three broad categories:

There are five creative design patterns: factory method design pattern, abstract plant design pattern, singleton design pattern, builder design pattern, and prototype design pattern.

There are seven structural design patterns: adapter design pattern, decorator design pattern, agency design pattern, appearance design pattern, bridge design pattern, combination design pattern, and Xiangyuan design pattern.

There are eleven behavioral design patterns: policy design pattern, template method design pattern, observer design pattern, iterative sub-design pattern, responsibility chain design pattern, command design pattern, memorandum design pattern, state design pattern, visitor design pattern, intermediary design pattern, and interpreter design pattern.

1. Factory Method Pattern

Define an interface for creating objects, let the subclass decide which class to instantiate, and factory methods defer the instantiation of a class to its subclasses.

The idea is that in the factory design pattern, we create an object instead of creating it directly with the new keyword, but instead delegate the act of creating an object to another class, the factory class. Abstract the instantiation steps and let the subclass decide which class to instantiate.

Scenario: The factory design pattern can be used when a class does not know the class of the object it must create, or when creating different instances based on different conditions.

2. Abstract Factory Pattern

The Abstract Factory Design pattern is a creational design pattern that provides a way to create a set of related products without specifying their concrete classes.

Advantages: The implementation details of specific product categories are completely hidden, and there is no need to care about the creation details; Adding a new specific product category only needs to add a new specific product class and the corresponding specific factory class, which will not affect the existing system; Comply with the "open-closed" principle.

Disadvantages: It is difficult to add new product classes, and it is necessary to modify the abstract factory and all the concrete factory classes.

3.Singleton Pattern

The singleton design pattern is a common software design pattern that refers to having a private constructor and an exposed static method in a class that returns a unique instance of an object.

The application scenario of the singleton design pattern is that you need a class that can only create one instance, such as configuration class, log class, counter class, and so on.

Advantages: reduced memory overhead; Ensure global uniqueness; You can control the number of instances.

Cons: Inheritance is not supported; inflexibility; Conflicts with the principle of single responsibility.

4.Builder Pattern

The Builder design pattern is a generative design pattern that uses an abstract builder to build a complex object.

The idea is to separate the construction of a complex object from its representation so that the same build process can create different representations.

The builder design pattern is used when creating a complex object, you can use the builder design pattern to separate the creation of the complex object from its representation, making the build process clearer.

Pros: Build and presentation separation; Good encapsulation; Complex objects can be constructed.

Disadvantages: difficult to control the components of the product; There are too many components of a product, and there may be many specific builder classes.

5. Prototyping patterns

A prototyping pattern is a generative design pattern that uses a prototype object to create a new object.

The idea is to create a new instance by copying an existing one, not by using the new keyword.

Prototyping patterns can come in handy when class creation is expensive or when complex operations are required in constructors.

Advantages: excellent performance; Simplify the creation process; High flexibility.

Disadvantages: Equipping the cloning method requires a large transformation of the function of the class, which is a very risky change; The Cloneable interface must be implemented; When using the prototyping pattern, you cannot use the final type.

6. Adapter Pattern

An adapter design pattern is a structural design pattern that transforms the interface of one class into another interface that the customer wants.

The idea is to convert the interface of one class into another interface that the customer wants, so that classes that are otherwise incompatible can work together.

The adapter design pattern is used when you want to use an existing class, but its interface does not match your requirements, you can use the adapter design pattern to solve this problem.

Advantages: improved class reusability; Increased transparency of classes; High flexibility.

Disadvantages: increased complexity of the system; Increase the difficulty of understanding and designing the system.

7.Decorator Pattern

The Decorator Design pattern is a structural design pattern that adds new functionality to an object without changing its structure.

The idea is to enhance the functionality of a class without changing its structure.

The Decorator Design pattern is used when you want to add new functionality to a class and don't want to change its structure.

8. Facade Pattern

A design pattern is a structural design pattern that provides a simple interface to a complex subsystem so that clients can easily access the subsystem.

The idea is to provide a simple interface to complex subsystems so that clients can easily access them. It applies the dependency inversion principle.

Scenarios are scenarios where simple interfaces need to be provided for complex subsystems.

9.Bridge Pattern

The bridging design pattern is a structural design pattern that decouples abstractions and implementations so that they can vary independently. It applies the principle of interface isolation.

Application scenarios are scenarios that require decoupling abstraction and implementation.

10.Proxy Pattern

A proxy design pattern is a structural design pattern that provides another object with a stand-in or proxy to control access to that object. It applies Dimit's law.

An application scenario is a scenario where you need to provide a stand-in or proxy for another object.

11.Composite Pattern

The Composite Design pattern is a structural design pattern that combines objects into a tree structure so that clients can use a uniform interface to work with individual and combined objects. Its principle is the principle of synthetic multiplexing.

An application scenario is a scenario where objects need to be combined into a tree structure.

12.Chain of Responsibility Pattern

It is a behavioral design pattern that allows the sender of a request to send a request to a series of processors without needing to know who the processor is, and eventually the processor handles it.

Its principle is to minimize the coupling between the request sender and the processor, which helps to increase the flexibility and scalability of the system.

13.Command Pattern

The command design pattern is a behavioral design pattern that encapsulates a request into an object so that other objects can be parameterized using different requests, queues, or logs.

Its principle is to separate requests from its originators and executors in order to achieve a low-coupling, highly cohesive system architecture.

14.Interpreter Pattern

An interpreter design pattern is a behavioral design pattern that uses grammar rules to interpret data entered by the consumer to implement the functionality of a program.

Its principle is to interpret the data by using simple grammar rules in order to implement program functions more easily.

15.Iterator Pattern

The Iterator design pattern is a behavioral design pattern that uses iterator objects to traverse a container, enabling traversal of elements in a container.

Its principle is to separate the elements in the container from their traversal operations in order to achieve a low-coupling, high-cohesive system structure.

16.Mediator Pattern

The mediator design pattern is a behavioral design pattern that uses mediator objects to encapsulate interactions between a group of objects, reducing the coupling between these objects and increasing the flexibility and scalability of the system. Its principle is to encapsulate interactions between objects by using mediator objects in order to reduce coupling and increase the scalability of the system.

17.Observer Pattern

The observer design pattern is a behavioral design pattern that uses observer objects to observe subject objects so that observer objects are notified when subject objects change.

Its principle is to observe the subject object by using the observer object so that the observer object can be notified when the subject object changes.

18.State Pattern

A modal design pattern is a behavior design pattern that uses state objects to encapsulate state-related behavior in order to achieve different behaviors using different states.

Its principle is to encapsulate state-related behavior by using state objects so that different behaviors are implemented using different states.

19.Strategy Pattern

A policy design pattern is a behavioral design pattern that uses policy objects to encapsulate interchangeable algorithms to solve different problems using different algorithms.

Its principle is to encapsulate interchangeable algorithms by using policy objects in order to use different algorithms to solve different problems.

20.Template Pattern

The template method design pattern is a behavioral design pattern that uses template methods to define the basic structure of an algorithm in order to defer some specific steps to implementation in subclasses. Its principle is to define the basic structure of the algorithm by using a template method in order to defer some specific steps to the implementation in the subclass.

21.Memento Pattern

The memo design pattern is a behavioral design pattern that uses memo objects to store the internal state of an object so that it can be recovered when needed.

Its principle is to store the internal state of an object by using a memo object so that the object can be restored when needed.

22.Visitor Pattern

The visitor design pattern is a behavioral design pattern that uses a visitor object to access an object in order to add new actions without changing its structure.

Its principle is to access an object by using a visitor object in order to add new actions without changing its structure.

23.Flyweight Pattern

The Symyuan design pattern is a software design pattern for performance optimization that effectively supports a large number of fine-grained objects by sharing objects.

Principle: The Symyuan design pattern enables the reuse of the same or similar objects through sharing techniques. It improves the performance of your application by saving memory by allocating shared memory for similar objects.

Merit:

  1. It can greatly improve the performance of the application and improve the operation efficiency of the application;
  2. It can reduce the use of memory and improve the scalability of the application;
  3. It can improve the maintainability of the application and reduce the number of object creations.

Shortcoming:

  1. To implement the design pattern, it is necessary to separate the internal state and the external state, and the identification of the internal state requires sufficient analysis and programming;
  2. In the Xiangyuan design pattern, it is necessary to associate external states, which will increase complexity;
  3. The use of the Yuanyuan design pattern will increase the maintenance complexity of the system, and it is necessary to separate the internal state and the external state, and the identification of the internal state requires sufficient analysis and programming.

3. Usage examples

Factory Method Pattern

/*

Define an interface for creating objects, let the subclass decide which class to instantiate, and factory methods defer the instantiation of a class to its subclasses.

The idea is that in the factory design pattern, we create an object instead of creating it directly with the new keyword, but instead delegate the act of creating an object to another class, the factory class. Abstract the instantiation steps and let the subclass decide which class to instantiate.

Scenario: The factory design pattern can be used when a class does not know the class of the object it must create, or when creating different instances based on different conditions.

*/

/*

Simple factory mode

First, let's create an abstract class that represents the order with a method that processes the order. Then, we create two concrete order classes, and , representing online and offline orders, implement the interface, and override the method. Next, we create a factory class that creates different order objects depending on the order type. Finally, we create order objects using the factory class and call their methods.Orderprocess()OnlineOrderOfflineOrderOrderprocess()OrderFactoryprocess()

*/

Abstract class Order

abstract class Order {

public abstract void process();

}

Online orders

class OnlineOrder extends Order {

@Override

public void process() {

System.out.println("Processing online order.");

}

}

//线下订单

class OfflineOrder extends Order {

@Override

public void process() {

System.out.println("Processing offline order.");

}

}

Factory class OrderFactory

class OrderFactory {

public static Order createOrder(String type) {

switch (type) {

case "online":

return new OnlineOrder();

case "offline":

return new OfflineOrder();

default:

throw new IllegalArgumentException("Invalid order type: " + type);

}

}

}

client

public class Main {

public static void main(String[] args) {

Order onlineOrder = OrderFactory.createOrder("online");

onlineOrder.process();

Order offlineOrder = OrderFactory.createOrder("offline");

offlineOrder.process();

}

}

Abstract Factory Pattern

/*

The Abstract Factory Design pattern is a creational design pattern that provides a way to create a set of related products without specifying their concrete classes.

*/

/**

* abstract factory

class */public abstract class AbstractCouponFactory { /** * Create coupon

*

/

public abstract Coupon createCoupon();

/** * Create Event

*/

public abstract Promotion createPromotion();

}

/** * coupon class

*/

public abstract class Coupon {

public abstract void useCoupon();

}

/** * New User Coupon

*/

public class NewUserCoupon extends Coupon {

public void useCoupon() {

System.out.println("Use New User Coupon");

}

}

/** * Activity

*/

public abstract class Promotion {

public abstract void startPromotion();

}

/**

* Double 11

*/

public class DoubleElevenPromotion extends Promotion {

public void startPromotion() {

System.out.println("Start Double 11");

}

}

/** * Mother and Baby Coupon Factory

*/

public class MotherAndBabyCouponFactory extends AbstractCouponFactory {

public Coupon createCoupon() {

return new NewUserCoupon();

}

public Promotion createPromotion() {

return new DoubleElevenPromotion();

}}

/** * Client

Code

*/

public class Client {

public static void main(String[] args) {

AbstractCouponFactory factory = new MotherAndBabyCouponFactory();

Coupon coupon = factory.createCoupon();

Promotion promotion = factory.createPromotion();

coupon.useCoupon();

promotion.startPromotion();

}

}

Singleton design pattern

/*

The idea of the singleton design pattern is to limit the instantiation of a class to an object, and there can be only one instance of a class.

Its application scenarios are mainly in the case of global control required, such as in e-commerce platforms, the control of the order process, can use the singleton design pattern.

In a multithreaded environment, the combination of double-check locks and the volatile keyword guarantees thread safety and correctness in singleton mode.

*/

public class OrderService {

private OrderService() {

}

Private static variables to hold instances

private volatile static OrderService instance;

Provide a global access point

public static OrderService getInstance() {

if (instance == null) {

synchronized (OrderService.class) {

if (instance == null) {

instance = new OrderService();

}

}

}

return instance;

}

public void placeOrder(Order order) {

//...

}

}

Prototyping patterns

/*

The idea of the prototyping pattern is to create a new object by copying a prototype. Its application scenario is generally when creating complex objects, you can first copy a prototype for some initialization work.

Then modify it. In marketplaces, you can use the prototyping pattern to create order objects and avoid repetitive initialization efforts.

*/

public class Order implements Cloneable {

private String orderId;

private List<String> items;

public Order(String orderId, List<String> items) {

this.orderId = orderId;

this.items = items;

}

public Order clone() {

try {

return (Order) super.clone();

}

catch (CloneNotSupportedException e) {

e.printStackTrace(); return null;

}

}

}

Builder design patterns

/*

The idea of the builder design pattern is to separate the construction of a complex object from its representation, so that the same build process can create different representations. Its application scenario is generally when creating complex objects.

The creation process of complex objects can be split to make the creation process clearer. In marketplaces, you can use the builder design pattern to create order objects that break down complex build processes into them

Several steps, thus making the creation process clearer.

*/

public class OrderBuilder {

private String orderId;

private List<String> items;

public OrderBuilder setOrderId(String orderId) {

this.orderId = orderId;

return this;

}

public OrderBuilder setItems(List<String> items) {

this.items = items;

return this;

}

public Order build() {

return new Order(orderId, items);

}

}

Adapter design pattern

/*

The adapter pattern is a structural design pattern that transforms the interface of one class into the interface expected by another client. In this pattern, the adapter class acts as a bridge between two incompatible interfaces, transforming the interface of one or more classes into the interface expected by the client. The following is sample code for a product-based Java adapter design pattern:

*/

// 目标接口

interface Product {

String getName();

double getPrice();

}

// 适配者类

class LegacyProduct {

private final String title;

private final double cost;

public LegacyProduct(String title, double cost) {

this.title = title;

this.cost = cost;

}

public String getTitle() {

return this.title;

}

public double getCost() {

return this.cost;

}

}

// 适配器类

class ProductAdapter implements Product {

private final LegacyProduct legacyProduct;

public ProductAdapter(LegacyProduct legacyProduct) {

this.legacyProduct = legacyProduct;

}

@Override

public String getName() {

return legacyProduct.getTitle();

}

@Override

public double getPrice() {

return legacyProduct.getCost();

}

}

// 客户端代码

public class AdapterDemo {

public static void main(String[] args) {

LegacyProduct legacyProduct = new LegacyProduct("Product A", 12.34);

Product product = new ProductAdapter(legacyProduct);

System.out.println(product.getName()); // 输出:Product A

System.out.println(product.getPrice()); // 输出:12.34

}

}

Decorator design pattern

/*

The idea of the Decorator Design pattern is to dynamically attach responsibility to objects. Its application scenario is generally when the original class does not meet the customer's needs, and it can be passed without changing the original class

Decorator design patterns to dynamically add new features. In e-commerce platforms, you can use the decorator design pattern to add new features to order objects, such as discount functions, without changing the original order object.

*/

public class OrderDecorator {

private Order order;

public OrderDecorator(Order order) {

this.order = order;

}

public void setDiscount(double discount) {

order.setDiscount(discount);

}

public double getDiscount() {

return order.getDiscount();

}

}

Exterior design patterns

/*

The idea of a design pattern is to provide a consistent interface to a set of interfaces in a subsystem, making the subsystem easier to use. Its application scenarios are generally in complex systems, and design patterns can be used

to simplify the interface of the system, making the system easier to use. In e-commerce platforms, design patterns can be used to simplify the interface of the order system and make the order system easier to use.

*/

public class OrderFacade {

private OrderService orderService;

private OrderBuilder orderBuilder;

private OrderAdapter orderAdapter;

private OrderDecorator orderDecorator;

public OrderFacade() {

orderService = OrderService.getInstance();

orderBuilder = new OrderBuilder();

orderAdapter = new OrderAdapter();

orderDecorator = new OrderDecorator();

}

public void placeOrder(Order order) {

orderService.placeOrder(order);

}

public Order buildOrder(String orderId, List<String> items) {

return orderBuilder.setOrderId(orderId).setItems(items).build();

}

public OrderAdapter getOrderAdapter(Order order) {

return new OrderAdapter(order);

}

public OrderDecorator getOrderDecorator(Order order) {

return new OrderDecorator(order); }

}

Bridging design patterns

/*

The idea of bridging design patterns is to separate abstraction and implementation so that they can vary independently. Its application scenario is generally when multiple dimensions of change exist, and the bridge design pattern can be used to separate abstraction and implementation.

So that abstraction and implementation can vary independently. In e-commerce platforms, you can use the bridge design pattern to create shopping cart objects, separating the abstraction and implementation of the shopping cart, so that the abstraction and reality of the shopping cart are made

It can now be changed independently.

*/

public abstract class Cart {

protected CartImplementor implementor;

public Cart(CartImplementor implementor) {

this.implementor = implementor;

}

public abstract void addItem(String item);

public abstract void removeItem(String item);

public abstract List<String> getItems();

}

Proxy design pattern

/*

The idea of the proxy design pattern is to provide a proxy for other objects to control access to that object. Its application scenario is generally to use proxy design patterns to control access to an object when accessing it.

In marketplaces, you can control access to shopping carts by using proxy design patterns to access shopping cart objects.

*/

public class CartProxy implements Cart {

private Cart cart;

public CartProxy(Cart cart) {

this.cart = cart;

}

@Override

public void addItem(String item) {

cart.addItem(item);

}

@Override

public void removeItem(String item) {

cart.removeItem(item);

}

@Override

public List<String> getItems() {

return cart.getItems();

}

}

Combined design patterns

/*

The idea of the Compositional Design pattern is to combine objects into a tree structure to represent a part-whole hierarchy. Its application scenario is generally in the tree structure, you can use the combination design pattern to combine objects into a tree structure,

Thus representing a part-whole hierarchy. In marketplaces, you can use the Composition Design pattern to organize cart objects, combining cart objects into a tree structure that represents a part-to-whole hierarchy.

*/

public class CartComposite extends CartComponent {

private List<CartComponent> components = new ArrayList<>();

@Override

public void add(CartComponent component) {

components.add(component);

}

@Override

public void remove(CartComponent component) {

components.remove(component);

}

@Override

public int getTotalPrice() {

int totalPrice = 0;

for (CartComponent component : components) {

totalPrice += component.getTotalPrice();

}

return totalPrice;

}

}

Chain of responsibility design patterns

/*

The idea behind the chain of responsibility design pattern is to separate the processors of a request, and each processor responds to the request, thus forming a chain where each processor can decide whether to pass the request to the next processor.

Its application scenario is generally when multiple processing methods exist, the chain of responsibility design pattern can be used to separate the processors of the request, so that a chain is formed between the processors. In e-commerce platforms,

You can use the chain of responsibility design pattern to work with cart objects, separating the processors of the cart so that a chain is formed between the processors.

*/

public abstract class CartHandler {

protected CartHandler nextHandler;

public void setNextHandler(CartHandler nextHandler) {

this.nextHandler = nextHandler;

}

public abstract void handle(Cart cart);

}

Command design pattern

/*

The idea of the command design pattern is to encapsulate a request into an object so that other objects can be parameterized with different requests, queues, or logs. Its application scenarios are generally when the requests are different.

You can use command design patterns to encapsulate requests into objects that parameterize other objects with different requests. In marketplaces, you can use command design patterns to perform actions on shopping cart objects.

Encapsulate the operation of the shopping cart into objects, parameterizing other objects with different requests.

*/

public interface Command {

void execute(Cart cart);

}

public class AddItemCommand implements Command {

private String item;

public AddItemCommand(String item) {

this.item = item;

}

@Override

public void execute(Cart cart) {

cart.addItem(item);

}

}

Interpreter design patterns

The idea of the /* interpreter design pattern is to define a language for a specific context, define the grammar of that language, and then use that grammar to interpret sentences in the language. Its application scenario is generally in a specific context, you can use the interpreter design pattern to define a language, and use the grammar of that language to interpret sentences. In e-commerce platforms, you can use the interpreter design pattern to explain the operation of the shopping cart object, define a language to describe the operation of the shopping cart, and then use the grammar of that language to explain the sentence to complete the operation of the shopping cart.

*/

public class CartExpressionParser {

public void parse(String expression, Cart cart) {

String[] tokens = expression.split(" ");

for (String token : tokens) {

if (token.equals("add")) {

String item = tokens1;

cart.addItem(item);

}

else if (token.equals("remove")) {

String item = tokens1;

cart.removeItem(item);

}

}

}

}

Iterator design pattern

/*

The idea behind the Iterator design pattern is to provide a way to access individual elements in an aggregated object sequentially without exposing the internal representation of the object. Its application scenario is generally in the aggregate object,

You can use the Iterator design pattern to provide a way to access elements in an aggregate object sequentially without exposing the internal representation of the object. In marketplaces, you can use iterators

Design patterns to traverse payment objects, providing a way to access elements in a payment object sequentially without exposing the internal representation of the object.

*/

public interface Iterator {

boolean hasNext();

Object next();

}

public class PaymentIterator implements Iterator {

private Payment[] payments;

private int index;

public PaymentIterator(Payment[] payments) {

this.payments = payments;

}

@Override

public boolean hasNext() {

if (index >= payments.length || paymentsindex == null) {

return false;

} else {

return true;

}

}

@Override

public Object next() {

Payment payment = paymentsindex;

index++;

return payment;

}

}

Mediator design pattern

/*

The idea of the mediator design pattern is to encapsulate the interaction between a series of objects with an intermediary object, so that the objects do not need to explicitly reference each other, so that they are loosely coupled and can change the interaction between them independently.

Its application scenario is generally when there are complex reference relationships between multiple objects, and the intermediary design pattern can be used to encapsulate these complex reference relationships, so that objects do not need to explicitly reference each other.

This makes it loosely coupled. In marketplaces, you can use the intermediary design pattern to encapsulate interactions between payment objects so that payment objects do not need to explicitly reference each other, making them loosely coupled.

*/

public class Mediator {

private List<Payment> payments;

public Mediator(List<Payment> payments) {

this.payments = payments;

}

public void makePayment(Payment payment) {

payments.forEach(p -> {if (p != payment) {p.receivePayment(payment);}});

}

}

Observer design patterns

/*

The idea of the observer design pattern is to define a one-to-many dependency between objects so that whenever an object changes state, all objects that depend on it are notified and updated automatically. Its application scenarios are generally in

When there is a one-to-many dependency between objects, you can use the observer design pattern to define a one-to-many dependency between objects so that whenever an object changes state, all objects that depend on it are notified

And update automatically. In e-commerce platforms, the observer design pattern can be used to define one-to-many dependencies between payment objects, so that whenever a payment object changes state, all payment objects that depend on it will win

to notifications and update automatically.

*/

public interface Observer {

void update(Payment payment);

}

public class PaymentSubject {

private List<Observer> observers = new ArrayList<>();

public void addObserver(Observer observer) {

observers.add(observer);

}

public void removeObserver(Observer observer) {

observers.remove(observer);

}

public void notifyObservers(Payment payment) {

for (Observer observer : observers) {

observer.update(payment);

}

}

}

State design patterns

/*

The idea of the state design pattern is to allow an object to change its behavior when its internal state changes, and the object looks like it changed its class. Its application scenario is generally in the behavior of an object depends on its state,

You can use state design patterns to allow an object to change its behavior when its internal state changes, and the object looks like it changed its class. In marketplaces, you can use the status design pattern to allow payment objects to

When its internal state changes, it changes its behavior, and the payment object looks like it has changed its class.

*/

public interface PaymentState {

void doAction(PaymentContext context);

}

public class PaymentContext {

private PaymentState paymentState;

public PaymentContext() {

paymentState = null;

}

public void setState(PaymentState state) {

this.paymentState = state;

}

public PaymentState getState() {

return paymentState;

}

public void doAction() {

paymentState.doAction(this);

}

}

Policy design pattern

/*

The idea of the strategy design pattern is to define a series of algorithms, encapsulate them one by one, and make them interchangeable. Its application scenario is generally in the case of multiple classes with only slightly different algorithms or behaviors.

You can use the policy design pattern to define a series of algorithms, encapsulate them one by one, and make them interchangeable. In e-commerce platforms, you can use the strategy design pattern to define payment algorithms and put them one by one

encapsulated and make them interchangeable.

*/

public interface PaymentStrategy {

void pay(int amount);

}

public class CreditCardStrategy implements PaymentStrategy {

private String name;

private String cardNumber;

private String cvv;

private String dateOfExpiry;

public CreditCardStrategy(String name, String cardNumber, String cvv, String dateOfExpiry) {

this.name = name;

this.cardNumber = cardNumber;

this.cvv = cvv;

this.dateOfExpiry = dateOfExpiry;

}

@Override

public void pay(int amount) {

System.out.println(amount + " paid with credit/debit card");

}

}

Template method design pattern

The idea of the /* template approach design pattern is to define the skeleton of an algorithm in operation while deferring some steps to the implementation in subclasses. Its application scenario is generally to implement the invariant part of an algorithm at one time and leave the variable part to it

When subclasses are implemented, you can use the template approach design pattern to define the skeleton of an algorithm in operation, while deferring some steps to the implementation in the subclass. In marketplaces, you can use template methods to design patterns to define the calculation of payment operations

method the implementation of the skeleton, while deferring some steps to the subclass.

*/

public abstract class PaymentTemplate {

protected abstract void doPayment();

public void payment() {

doPayment();

}

}

public class CreditCardPayment extends PaymentTemplate {

private String name;

private String cardNumber;

private String cvv;

private String dateOfExpiry;

public CreditCardPayment(String name, String cardNumber, String cvv, String dateOfExpiry) {

this.name = name;

this.cardNumber = cardNumber;

this.cvv = cvv; this.dateOfExpiry = dateOfExpiry;

}

@Override

protected void doPayment() {

System.out.println("Paid with credit/debit card");

}

}

Memo design pattern

/*

The idea behind the memo design pattern is to capture the internal state of an object without breaking the encapsulation, and save that state outside of the object so that the object can be restored later when needed

The state that was originally saved. Application scenarios: The memo design pattern can be used for scenarios such as revocation operations, such as the coupon business of e-commerce platforms, and the memo design mode can be used to record the status of coupon use in case it needs to be revoked

The coupon status can be restored when operating. Taking the coupon business of the e-commerce platform as an example, the specific Java code can be referred to as follows:

*/

public class Memento {

private String state;

public Memento(String state) {

this.state = state;

}

public String getState() {

return state;

}

}

public class CouponService {

private Memento memento;

Record the current coupon status

public void saveMemento(Memento memento) {

this.memento = memento;

}

Restore coupon usage

public void restoreMemento(Memento memento) {

this.memento = memento;

}

}

Visitor design patterns

/*

Encapsulates operations that act on elements of a data structure, and it can define new operations that act on those elements without changing the data structure.

Application scenario: The visitor design pattern is suitable for systems with relatively stable data structures, and decoupling data structures and algorithms can better cope with changes. For example, the coupon business of the e-commerce platform,

Coupons can be managed uniformly through visitor design patterns, and different operations can be adopted according to different coupon types. Taking the coupon business of the e-commerce platform as an example, the specific Java code can be referred to as follows:

*/

public class CouponVisitor {

public void visit(DiscountCoupon coupon) {

// do something

}

public void visit(CashCoupon coupon) {

// do something

}

}

Interpreter design patterns

/*

Create an interpreter for a specific language that interprets sentences in that language.

Application scenario: The interpreter design pattern is suitable for situations where the language grammar is relatively simple, such as the coupon business of e-commerce platforms, and the interpreter design pattern can be used

to analyze the rules for using coupons, such as how much money is available. Taking the coupon business of the e-commerce platform as an example, the specific Java code can be referred to as follows:

public abstract class AbstractExpression {

public abstract boolean interpret(String context);

}

public class TerminalExpression extends AbstractExpression {

private String data;

public TerminalExpression(String data) {

this.data = data;

}

@Override

public boolean interpret(String context) {

if (context.contains(data)) {

return true;

} return false;

}

}

Mediator design pattern

/*

Using an intermediary object to encapsulate a series of object interactions so that objects do not need to explicitly reference each other, so that the coupling is loose and the interaction between them can be changed independently.

Application scenario: The mediator design pattern is suitable for the close coupling between multiple objects, such as the coupon business of an e-commerce platform, and the relationship between various links such as coupon issuance, use, and verification can be adjusted through the mediator design pattern

for efficient operational management. Taking the coupon business of the e-commerce platform as an example, the specific Java code can be referred to as follows:

*/

public class CouponMediator {

private List<CouponUser> users;

public CouponMediator() {

this.users = new ArrayList<>();

}

public void addUser(CouponUser user) {

this.users.add(user);

}

public void distributeCoupon(Coupon coupon) {

for (CouponUser user : users) {

user.receiveCoupon(coupon);

}

}

public void redeemCoupon(Coupon coupon) {

for (CouponUser user : users) {

user.redeemCoupon(coupon);

}

}

}

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2023-04-27,如有侵权请联系 cloudcommunity@tencent 删除voidclassobjectpublicstring