A whim of the milk tea shop started the Java design pattern: Flyweight pattern

definition

Flyweight mode is the structure mode of objects. Flyweight mode efficiently supports a large number of fine-grained objects in a shared manner. It is mainly used to reduce the number of objects created to reduce memory usage and improve performance.

The key to sharing the Flyweight object is to distinguish between the intrinsic state and the extrinsic state

The intrinsic state is stored inside the flyweight object, and will not change with the change of the environment, therefore, a flyweight object can have an intrinsic state and can be shared

The extrinsic state changes as the environment changes and is not a state that can be shared. The extrinsic state of the flyweight object must be saved by the client, and it must be used after the flyweight object is created. Passed to the inside of the Flyweight object

The extrinsic state cannot affect the intrinsic state of the Flyweight object, in other words, they are independent of each other

intention

Use sharing technology to effectively support a large number of fine-grained objects

Mainly solve the problem

When there are a large number of objects, it may cause memory overflow. We abstract the common parts. If there are the same business requests, we will directly return the existing objects in memory to avoid re-creation.

When to use

There are a large number of objects in the system and consume a lot of memory. Most of the states of these objects can be externalized. These objects can be divided into many groups according to the intrinsic state. When the extrinsic objects are removed from the objects, each Group objects can be replaced by one object

Pros and cons

Advantages:
greatly reduce the creation of objects, reduce system memory, and improve efficiency

Disadvantages: It
makes the system more complex, in order to make the objects can be shared, some state needs to be externalized

structure

Insert picture description here
Roles involved:

  • Abstract Flyweight role: the superclass of all concrete Flyweight classes, which specify the interfaces that need to be implemented for these classes
  • ConcreteFlyweight role: implements the interface specified by the abstract flyweight role. If there is an intrinsic state, it must provide storage space for the intrinsic state. The intrinsic state of the flyweight object must have nothing to do with the environment, so that Flyweight objects can coexist in the system
  • FlyweightFactory factory role: responsible for creating and managing flyweight roles. This role must ensure that the Flyweight object can be appropriately shared by the system. When the client calls the flyweight object, the FlyweightFactory will check whether it is already in the system. If you have a Flyweight object that meets the requirements, provide this object if you have one. If there is no Flyweight factory, you should create a suitable Flyweight object.
  • Client role: This role needs to maintain a reference to all flyweight objects, and needs to store the extrinsic state of all flyweight objects by itself

The corresponding source code is as follows:

public abstract class Flyweight {
    
    

    /** 一个示意性的方法,参数state是外蕴状态 */
    public abstract void operation(String state);
}
public class ConcreteFlyweight extends Flyweight {
    
    

    private int intrinsicState;

    public ConcreteFlyweight(int intrinsicState) {
    
    
        this.intrinsicState = intrinsicState;
    }

    /**
     * 外蕴状态作为参量传入
     * 改变方法的行为
     * 并不改变对象的内蕴状态
     */
    @Override
    public void operation(String state) {
    
    

        System.out.println("内蕴状态:" + intrinsicState + ",,外蕴状态:" + state);
    }
}
public class FlyweightFactory {
    
    

    private Map<String, Flyweight> map = new HashMap();

    private Flyweight flyweight;

    public FlyweightFactory() {
    
    

    }

    //内蕴状态作为参量传入
    public Flyweight factory(int state) {
    
    
        if (map.containsKey(state)) {
    
    
            return map.get(state);
        } else {
    
    
            Flyweight fly = new ConcreteFlyweight(state);
            map.put(String.valueOf(state), fly);
            return fly;
        }
    }

    public void checkFlyweight() {
    
    
        Flyweight fly;
        int i = 0;
        Iterator iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
    
    
            Map.Entry e = (Map.Entry) iterator.next();
            System.out.println("Item    " + (++i) + ":" + e.getKey());
        }
    }
}
public class Client {
    
    
    public static void main(String[] args) {
    
    
        FlyweightFactory factory = new FlyweightFactory();
        Flyweight flyweight = factory.factory(888);
        flyweight.operation("第一次");
        flyweight = factory.factory(999);
        flyweight.operation("第二次");
        flyweight = factory.factory(888);
        flyweight.operation("第三次");
        System.out.println();
        factory.checkFlyweight();
    }
}

Insert picture description here

Examples of milk tea stalls

In this milk tea stall, there are a series of flavors of milk tea. After the guests came, they paid for the milk tea and left. The milk tea has an internal state, that is, its taste. There is no external environmental impact, that is, there is no external state.

If an object is created for each cup of milk tea in the system, then many small objects will be created. If distinguished according to the taste of milk tea, only one object will be created for each flavor of milk tea, and then shared

The following code is used to achieve:
abstract Flyweight role, which is the interface that each milk tea flavor needs to implement:

public abstract class Order {
    
    

    /** 将咖啡卖给客人 */
    public abstract void sellingCoffee();

    /** 返回奶茶的口味 */
    public abstract String getFlavor();
}

The specific Flyweight role, the taste of milk tea realizes the interface provided by the abstract Flyweight role:

public class Flavor extends Order {
    
    

    private String flavor;

    public Flavor(String flavor) {
    
    
        this.flavor = flavor;
    }

    @Override
    public void sellingCoffee() {
    
    
        System.out.println("将奶茶卖给客人,奶茶口味为:" + this.flavor);
    }

    @Override
    public String getFlavor() {
    
    
        return this.flavor;
    }
}

The stall owner provides milk tea, which is the Xiangyuan factory, responsible for creating and managing the Xiangyuan role:

public class FlavorFactory {
    
    

    private Order[] flavors = new Flavor[10];

    private int ordersMade = 0;
    private int totalFlavors = 0;

    /** 根据所需要的口味提供奶茶 */
    public Order getOrder(String flavor) {
    
    
        if (ordersMade > 0) {
    
    
            for (int i=0; i<ordersMade; i++) {
    
    
                if (flavor.equals(flavors[i].getFlavor())) {
    
    
                    return flavors[i];
                }
            }
        }
        flavors[ordersMade] = new Flavor(flavor);
        totalFlavors++;
        return flavors[ordersMade++];
    }

    /** 返回所有的奶茶口味 */
    public int getTotalFlavors() {
    
    
        return totalFlavors;
    }
}

Client:

public class Client {
    
    
    private static Order[] flavors = new Flavor[10];

    private static int ordersMade = 0;

    private static  FlavorFactory factory;

    private static void taskOrder(String flavor) {
    
    
        flavors[ordersMade++] = factory.getOrder(flavor);
    }

    public static void main(String[] args) {
    
    
        factory = new FlavorFactory();

        taskOrder("原味");
        taskOrder("香蕉");
        taskOrder("原味");
        taskOrder("草莓");
        taskOrder("草莓");
        for (int i=0; i<ordersMade; i++) {
    
    
            flavors[i].sellingCoffee();
        }
        System.out.println("总共买奶茶人数:" + ordersMade);
        System.out.println("总共卖出奶茶口味数:" + factory.getTotalFlavors());
    }
}

Insert picture description here
It can be seen that although the customer bought 5 cups of milk tea, there are only three flavors of milk tea

Example of milk tea shop

The milk tea stall does not provide tables and chairs for the guests, that is, there is no external environmental impact. Now the milk tea shop provides tables and chairs, then the tables and chairs are the extrinsic state. The
abstract Flyweight role is the interface that each milk tea taste needs to implement:

public abstract class Order {
    
    

    /** 将咖啡卖给客人 */
    public abstract void sellingCoffee(Table table);

    /** 返回奶茶的口味 */
    public abstract String getFlavor();
}

The specific Flyweight role, the taste of milk tea realizes the interface provided by the abstract Flyweight role:

public class Flavor extends Order {
    
    

    private String flavor;

    public Flavor(String flavor) {
    
    
        this.flavor = flavor;
    }

    @Override
    public void sellingCoffee(Table table) {
    
    
        System.out.println("将奶茶卖给客人,奶茶口味为:" + this.flavor + ",客人所坐桌子号码为:" + table.getNumber());
    }

    @Override
    public String getFlavor() {
    
    
        return this.flavor;
    }
}

The milk tea shop provides milk tea, which is the Xiangyuan factory, responsible for creating and managing Xiangyuan roles:

public class FlavorFactory {
    
    

    private Order[] flavors = new Flavor[10];

    private int ordersMade = 0;
    private int totalFlavors = 0;

    /** 根据所需要的口味提供奶茶 */
    public Order getOrder(String flavor) {
    
    
        if (ordersMade > 0) {
    
    
            for (int i=0; i<ordersMade; i++) {
    
    
                if (flavor.equals(flavors[i].getFlavor())) {
    
    
                    return flavors[i];
                }
            }
        }
        flavors[ordersMade] = new Flavor(flavor);
        totalFlavors++;
        return flavors[ordersMade++];
    }

    /** 返回所有的奶茶口味 */
    public int getTotalFlavors() {
    
    
        return totalFlavors;
    }
}

Environmental roles, tables and chairs:

public class Table {
    
    

    /** 桌子号码 */
    private int number;

    public Table(int number) {
    
    
        this.number = number;
    }

    public int getNumber() {
    
    
        return number;
    }

    public void setNumber(int number) {
    
    
        this.number = number;
    }
}

Client:

public class Client {
    
    
    private static Order[] flavors = new Flavor[10];

    private static int ordersMade = 0;

    private static FlavorFactory factory;

    private static void taskOrder(String flavor) {
    
    
        flavors[ordersMade++] = factory.getOrder(flavor);
    }

    public static void main(String[] args) {
    
    
        factory = new FlavorFactory();

        taskOrder("原味");
        taskOrder("香蕉");
        taskOrder("原味");
        taskOrder("草莓");
        taskOrder("草莓");
        for (int i=0; i<ordersMade; i++) {
    
    
            flavors[i].sellingCoffee(new Table(i+1));
        }
        System.out.println("总共买奶茶人数:" + ordersMade);
        System.out.println("总共卖出奶茶口味数:" + factory.getTotalFlavors());
    }
}

Insert picture description here

Under what circumstances to use Flyweight mode

  • There are a large number of objects in a system
  • These objects consume a lot of memory
  • Most of the state of these objects can be externalized
  • These objects can be divided into many groups according to the intrinsic state. When the extrinsic state is removed from the object, each group can be replaced by an object
  • The software system does not rely on the identity of these objects, that is, these objects can be indistinguishable

Guess you like

Origin blog.csdn.net/qq_34365173/article/details/108174596