In depth understanding of factory mode & agent mode

Seven principles of OOP

  1. Opening and closing principle: open to extension and close to modification
  2. Richter substitution principle: inheritance must ensure that the properties owned by the superclass are still valid in the subclass
  3. Dependency Inversion Principle: interface oriented programming, not implementation oriented programming
  4. Single responsibility principle: control the granularity of classes, decouple objects and improve their cohesion
  5. Interface isolation principle: establish the special interface for each class they need
  6. Dimitri's Law: only talk to your direct friends, not strangers
  7. Synthesis Reuse Principle; Try to use the combination or aggregation relationship first, and then use the inheritance relationship

Factory mode

Core: instantiated objects do not use new, but use factory methods instead.
We will select real classes and create objects for unified management and control, so as to decouple our implementation classes

Three modes:
  • Simple factory mode
    It is used to produce any product in the same grade structure. Although it does not conform to the design principles to some extent, it is actually used most
  • Factory method model
    It is used to produce fixed products in the same hierarchical structure. It can be expanded by adding new factories without modifying existing classes
  • Abstract factory pattern
    Create other factories around a super factory, which is also called the factory of other factories
Application scenario
  • getInstance() method of Calender in JDK
  • connection object acquisition in JDBC
  • Creating management bean objects in the IOC container in Spring
  • CLass object newInstance method in reflection

Now suppose the customer wants to buy a car

public interface Car {
    //name
    void  name();
}
public class TeSla implements Car{
    @Override
    public void name() {
        System.out.println("This is Tesla");
    }
}
public class BaoMa implements Car{
    @Override
    public void name() {
        System.out.println("This is BMW");
    }
}

Customers want to get a car, our normal way of thinking is new object and then call the method.

        BaoMa baoMa=new BaoMa();
        TeSla teSla=new TeSla();
        baoMa.name();
        teSla.name();

This seems a little cumbersome, and customers have to go to new, so we consider whether we can have a factory to do it for us

This seems OK, but if you think about it carefully, there will be new problems. Suppose we need another type of car and have to modify the code, which does not comply with the opening and closing principle of one of the seven principles, so let's improve our code.

public interface CarFactory {
    //Equivalent to a large automobile factory
    Car getCar();
}

Now what type of car do we want? We only need to implement the interface, and then write the method. We don't need to modify the code, but only need to expand horizontally.

Abstract factory pattern

  • Definition: the abstract factory pattern provides an interface to create a series of related or interdependent objects without specifying their specific classes
  • The client does not depend on the details of how the product class instance is created and implemented
  • Emphasize that using a series of related product objects together requires a lot of repetitive code to create objects
  • It provides a library of a series of products. All products appear with the same interface, so that the client does not depend on the specific implementation

Code demonstration

Now there are two factories, one responsible for the production of mobile phones and the other responsible for the production of routers

//The router factory is dedicated to the production of routers
public interface RouterProduct {
    void open();
    void close();
    void setMs();
}

//The mobile phone factory specializes in producing mobile phones
public interface phoneFactory {
    void open();
    void sendMessage();
    void close();
}

There is also a general factory responsible for the production of these two factories (it's a little abstract, so it's good to understand)

public interface FactoryAll {
    //Production of mobile phones
    phoneFactory phoneProduct();
    //Production router
    RouterProduct routerProduct();
}

Now we want to produce a Huawei mobile phone and a Huawei router ok to realize the total factory interface

public class huaweiFactory implements FactoryAll{
    @Override
    public phoneFactory phoneProduct() {
        return new huaweiPhone();
    }
    @Override
    public RouterProduct routerProduct() {
        return new huaweiRouter();
    }
}

ok, now we can take the Huawei factory to produce Huawei products

  • Huawei mobile phone
public class huaweiPhone implements phoneFactory{
    @Override
    public void open() {
        System.out.println("Huawei mobile phone on");
    }

    @Override
    public void sendMessage() {
        System.out.println("Huawei mobile phone sends information");
    }

    @Override
    public void close() {
        System.out.println("Huawei mobile phone shutdown");
    }
}
  • Huawei router
public class huaweiRouter implements RouterProduct{
    @Override
    public void open() {
        System.out.println("Huawei router on");
    }

    @Override
    public void close() {
        System.out.println("Huawei router off");
    }

    @Override
    public void setMs() {
        System.out.println("Huawei router modification parameters");
    }
}

Simulated customer

public class Client {
    @Test
    public  void getProduct(){
        //Get factory
        huaweiFactory huaweiFactory=new huaweiFactory();
        //Want the factory to produce mobile phones
        phoneFactory phoneFactory = huaweiFactory.phoneProduct();
        //mobile phone
        phoneFactory.open();
        phoneFactory.sendMessage();
        phoneFactory.close();
        //Want a router
        RouterProduct routerProduct = huaweiFactory.routerProduct();
        //Router
        routerProduct.open();
        routerProduct.setMs();
        routerProduct.close();
    }
    @Test
    public void buy(){
        System.out.println("I want to see Huawei products");
        getProduct();
    }
}



This is easier to understand. I want Huawei products, so all the products I get are produced by a Huawei factory.
But let's think about what to do if the customer wants to see Huawei robots. The manufacturer should not only add interface codes in the General Factory, but also add implementation classes, and will modify a lot of codes. Isn't that his disadvantage

proxy pattern

  • Introduction:

For another example, the level of our king's glory is not enough, so we asked to call to help us play the game.

Let's start writing code now

There is an actor interface. The actor's duty is to play

public interface Actor {
    //Actors in movies
    void play();
}

Suppose the author is now a small fresh meat

public class jiaSen implements Actor{
    @Override
    public void play() {
        System.out.println("jiaSen I want to play a memorable film");
    }
}

Now jiaSen has an agent

public class agent implements Actor{
    private  jiaSen jiaSen;
    public agent(jiaSen jiaSen){
        this.jiaSen=jiaSen;
    }
    //Extra work done by the agent
    public void link(){
        System.out.println("Economic man Gang jiaSen Contact the company to find the film");
    }
    @Override
    public void play() {
        jiaSen.play();
        link();
    }
}


jiaSen is popular in movies now, so the agent wants to increase the money, but Nah, jiaSen said yes, but on the premise that you can only be my agent now
Don't be anyone else's

After negotiation, the broker finally agreed

       public agent(){
        this.jiaSen=new jiaSen();
    }
    //Add money
    public  void addMoney(){
        System.out.println("Add 1000 yuan");
    }

The agent is transparent when others see it..

Dynamic agent

  • However, the good times did not last long. The agent was too greedy. jiaSen felt that he was making less and less money. He wanted to find other agents and was afraid of being more greedy than this
  • So jiaSen decided to plan his time reasonably and decide to be his economic man.
 public static void main(String[] args) {
        jiaSen jiaSen=new jiaSen();
        Actor proxyInstance = (Actor) Proxy.newProxyInstance(jiaSen.getClass().getClassLoader(), jiaSen.getClass().getInterfaces(),
                (proxy, method, args1) -> {
            if (method.getName().equals("play")){
                method.invoke(jiaSen,args);
                System.out.println("jiaSen Take time to be your own agent");
            }else{
                return method.invoke(jiaSen,args);
            }
            return  null;
        });
        proxyInstance.play();
    }

Let's read this code

  • Java provides a Proxy class. Calling its newInstance method can generate a Proxy object of an object. This method requires three parameters

The difference between dynamic agent and static agent

  • Static proxy needs to write its own proxy class = = > the proxy class and the proxy class implement the same interface
  • Dynamic agents are generated dynamically through reflection mechanism

Disadvantages of static proxy:

  • If there are many methods in the interface, it will be troublesome and cumbersome to implement each method

Advantages of dynamic agent

  • The generation of proxy object is to use JDKAPI to dynamically build proxy object in memory, and will implement all methods of the interface by default

Keywords: Java Spring

Added by smclay on Sat, 15 Jan 2022 09:10:32 +0200