Design Mode - Combination Mode (Did you understand the double eleven combination discount)

Combination mode

The Composite Pattern, also known as the Part Whole Pattern, is used to treat a group of similar objects as a single object. The composition pattern composes objects according to a tree structure, which is used to represent parts and whole hierarchies. This type of design pattern is a structural pattern that creates a tree structure of groups of objects.

  • Main solution: It blurs the concepts of simple elements and complex elements in the problem of our tree structure. The client program can handle complex elements like simple elements, thereby decoupling the client program from the internal structure of complex elements.
  • How to solve: Branches and leaves implement a unified interface, and the interface is combined inside the branch.
  • When to use:
  1. You want to represent a part-whole hierarchy (tree structure) of objects.
  2. You want users to ignore the difference between composite objects and individual objects, and users will use all objects in the composite structure uniformly.
  • Usage scenarios: partial and whole scenarios, such as tree menu, management of files and folders.
advantage shortcoming
The high-level module calls are simple, and the nodes can be added freely. The declarations of leaves and branches are implementing classes, not interfaces, violating the Dependency Inversion Principle.


The tree structure of folders-files must be familiar. Files are regarded as leaf nodes (single objects), and folders are regarded as intermediate nodes (combined objects).
The composite mode enables users to have consistent access to individual objects and composite objects, that is, to allow users to process individual objects and composite objects in a consistent manner. Avoid distinguishing them during use and causing trouble.

  • Component : The object declaration interface in the composition for accessing and managing Component child components.
  • Leaf: A single/leaf object, the leaf node has no child nodes.
  • Composite: A combination/container object, which stores the behavior of sub-components and branch nodes, and implements operations related to sub-components, such as adding (add) and deleting (remove), etc. list implements containers and accommodates Component objects.

Demo

Take the double eleven discounts as an example, there are VIP discounts, event discounts, full discounts, store coupons, red envelopes...

The picture is taken from the network (papi sauce), invaded and deleted

Let's take a look at the general writing first:

This approach also works when users meet only one discount plan.
However, we are often careful to meet multiple discount schemes at the same time. At this time, we can use the combination mode to accommodate these single discount schemes in combination, and then define a strategy for resolving discount conflicts. Realize the unification of single objects and composite objects, so that the caller does not have to distinguish them when using them.


The composite object CompositeDiscount is defined as an abstract class, and SingleMinStrategy and MultipleStrategy inherit it, indicating the conflict resolution strategy, which is to take the minimum discount and the higher discount.
Generally, the solution to the discount conflict is a discount, but the merchants are often more shrewd, launching mutually exclusive coupons and the like, that is, taking the smallest discount. Other discount conflict policies can also be customized.

involved points factory pattern and strategy mode , DiscountFactory is the factory that instantiates the DiscountStrategy attribute of the Order class, and various discount strategies implement the same interface.

(Insert anti-climbing information) Blogger CSDN address: https://wzlodq.blog.csdn.net/

Code:

public interface DiscountStrategy {
    public double getTotal(double price);
}

public class VIPDiscount implements DiscountStrategy {
    //5% off
    @Override
    public double getTotal(double price) {
        return 0.95*price;
    }
}
public class ActivityDiscount implements DiscountStrategy{
    //10% off
    @Override
    public double getTotal(double price) {
        return 0.9*price;
    }
}

public class StoreDiscount implements DiscountStrategy{
    //40% off over 500
    @Override
    public double getTotal(double price) {
        return 500+0.6*(price-500);
    }
}
public abstract class CompositeDiscount implements DiscountStrategy {
    protected List<DiscountStrategy> strategies =new ArrayList(); //container
    public void add(DiscountStrategy discountStrategy){ //add leaf node
        strategies.add(discountStrategy);
    }

    @Override
    public double getTotal(double price) {
        return price;
    }
}

//Choose the lowest discount from a variety of discounts
public class SingleMinStrategy extends CompositeDiscount {
    @Override
    public double getTotal(double price) {
        double rtn=price;
        for (DiscountStrategy s: strategies) {
            rtn=Math.min(rtn,s.getTotal(price));
        }
        return rtn;
    }
}

//Multiple discounts with discounts
public class MultipleStrategy extends CompositeDiscount {
    @Override
    public double getTotal(double price) {
        double rtn = price;
        for (DiscountStrategy s : strategies) {
            rtn = s.getTotal(rtn);
        }
        return rtn;
    }
}
public class DiscountFactory {
    public DiscountStrategy create(String type){ //Factory to create corresponding policies
        //single discount strategy
        if("ynn".equals(type))return new VIPDiscount();
        else if("nyn".equals(type))return new StoreDiscount();
        else if("nny".equals(type))return new ActivityDiscount();
        else{  //Multiple discount strategies
            CompositeDiscount compositeDiscount;
            System.out.println("Please select conflict resolution: 1.fold up 2.lowest discount");
            Scanner scanner=new Scanner(System.in);
            int type2=scanner.nextInt();
            if(type2==1){
                compositeDiscount=new MultipleStrategy();
            }
            else{
                compositeDiscount=new SingleMinStrategy();
            }
            if(type.charAt(1)=='y')compositeDiscount.add(new StoreDiscount());
            if(type.charAt(0)=='y')compositeDiscount.add(new VIPDiscount());
            if(type.charAt(2)=='y')compositeDiscount.add(new ActivityDiscount());
            return compositeDiscount;
        }
    }
}
public class Order {
    public double price;
    private String type;
    public DiscountStrategy discountStrategy;
    public Order(double price) {
        this.price=price;
    }

    public void display(){
        System.out.println("Total price:"+price);
        System.out.println("whether or not VIP?y/n");
        Scanner scanner=new Scanner(System.in);
        type=scanner.next();
        System.out.println("Is it more than 500? y/n");
        String tmp;
        tmp=scanner.next();
        type+=tmp;
        System.out.println("Do you meet the event price? y/n");
        tmp=scanner.next();
        type+=tmp;
        DiscountFactory discountFactory=new DiscountFactory();
        double discountPrice=discountFactory.create(type).getTotal(price);
        System.out.println("discount:"+(price-discountPrice));
        System.out.println("Handle:"+discountPrice);

    }
}

public class Client {
    public static void main(String[] args) {
        Order order=new Order(620);
        order.display();
    }
}

operation result:


In this way, whether it is a single discount or multiple discounts, the client uses the same usage without distinguishing and worrying about it.

Originality is not easy, please do not reprint (this is not rich in visits)
Blogger Homepage: https://wzlodq.blog.csdn.net/
WeChat public account: oh lo dong chiang
If the article is helpful to you, remember to click three times ❤

Tags: Java Design Pattern OOP UML

Posted by Gaoshan on Sun, 01 May 2022 03:45:42 +0300