Design mode 11: enjoy element mode [structural mode]

Posted by jlhaslip on Sun, 24 Nov 2019 12:49:24 +0100

In the process of object-oriented programming, we sometimes face the problem of creating a large number of instances of the same or similar objects. Creating so many objects will consume a lot of system resources, which is a bottleneck of improving system performance. For example, black and white pieces in go and Gobang, coordinate points or colors in images, routers, switches and hubs in LAN, desks and stools in classroom, etc. These objects have many similarities. If we can extract and share the same parts of them, we can save a lot of system resources. This is the background of the sharing pattern.

Definition and characteristics

Definition of Flyweight pattern: using sharing technology to support reuse of a large number of fine-grained objects. It can reduce the number of objects to be created and avoid the cost of a large number of similar classes by sharing the existing oak, so as to improve the utilization of system resources.

The main advantage of the shareware mode is that only one copy of the same object is saved, which reduces the number of objects in the system, thus reducing the pressure of fine-grained objects in the system on memory.

Its main disadvantages are:

  1. In order to make objects can be shared, some states that cannot be shared need to be externalized, which will increase the complexity of the program.
  2. Reading the external state of the sharing mode will make the running time slightly longer.

Structure and Implementation

There are two states in the sharing mode:

  1. Internal state, that is, the shareable part that will not change with the change of environment;
  2. External state refers to the unshared part that changes with the environment. The key to the implementation of the sharing mode is to distinguish the two states in the application and externalize the external state. Next, we will analyze its basic structure and implementation method.

Structure of patterns

The main roles of the sharing mode are as follows.

  1. Abstract membership role (Flyweight): it is the base class of all the concrete membership classes. It is the public interface that the concrete membership specification needs to implement. The external state of the non membership is passed in as a parameter through a method.
  2. Concrete Flyweight role: implements the interface specified in the abstract role.
  3. Unshareable flyweight role: it is an external state that cannot be shared. It is injected into the relevant methods of specific sharers in the form of parameters.
  4. Flyweight Factory role: responsible for creating and managing the role. When a customer object requests a sharing object, the sharing factory checks whether there is a qualified sharing object in the system, and if so, provides it to the customer; if not, creates a new sharing object.

In the figure, UnsharedConcreteFlyweight and sharer roles contain the non shared external state information info; Flyweight is an abstract sharer role, which contains the sharer method operation(UnsharedConcreteFlyweight state), through which the non sharer external state is passed in as a parameter; ConcreteFlyweight is a specific sharer role, which contains the keyword key, It implements the abstract sharing element interface; FlyweightFactory is the sharing element factory role, which uses the keyword key to manage the specific sharing element; the customer role obtains the specific sharing element through the sharing element factory, and accesses the relevant methods of the specific sharing element.  

# Non shareable role
class UnsharedConcreteFlyweight(object):
    __info = None
    def __init__(self, info):
        self.__info = info

    @property
    def info(self):
        return self.__info

    @info.setter
    def info(self, info):
        self.__info = info

# Abstract sharing role
class Flyweight(object):
    def operation(self, state):
        '''
        :param state: UnsharedConcreteFlyweight
        :return:
        '''
        pass

#Specific role
class ConcreteFlyweight(Flyweight):
    __key = None

    def __init__(self, key):
        self.__key = key
        print("Specific enjoyment", key, "Created!")

    def operation(self, state):
        print("Specific enjoyment", self.__key, "Called,", end='')
        print("Non shareable information is:"+state.info)

# Xiangyuan factory role
class FlyweightFactory(object):
    __flyweights = dict()
    def get_flyweight(self, key):
        flyweight = self.__flyweights.get(key)
        if(flyweight!=None):
            print("Specific enjoyment", key, "Already exists, successfully obtained!")
        else:
            flyweight = ConcreteFlyweight(key)
            self.__flyweights[key]=flyweight
        return flyweight

if __name__ == '__main__':
    factory = FlyweightFactory()
    f1 = factory.get_flyweight('a')
    f2 = factory.get_flyweight('a')
    f3 = factory.get_flyweight('a')
    f11 = factory.get_flyweight('b')
    f12 = factory.get_flyweight('b')
    f1.operation(UnsharedConcreteFlyweight("First calla"))
    f2.operation(UnsharedConcreteFlyweight("Second calla"))
    f3.operation(UnsharedConcreteFlyweight("Third calla"))
    f11.operation(UnsharedConcreteFlyweight("First callb"))
    f12.operation(UnsharedConcreteFlyweight("Second callb"))

Application example

The application of enjoy element mode in Gobang game.

Analysis: Gobang, like go, contains many pieces of "black" or "white" color, so it's better to use the enjoy element mode.

In this example, the ChessPieces class is an abstract sharer role, which contains a DownPieces(Graphics g,Point pt) method of a drop; the WhitePieces and BlackPieces classes are specific sharer roles, which implement the drop method; the Point is the non sharer role, which specifies the location of the drop; the WeiqiFactory is the sharer factory role, which uses arraylis T to manage the Chessboard, and provides getcheckpieces (string type) method to get white or black; the customer class draws a Chessboard in the frame form by using the Graphics component, and implements mouseClick (mouseevent E) event processing method, which obtains white or black from the sharing factory and lands on the Chessboard according to the user's choice.

class Point(object):
    __x = None
    __y = None
    def __str__(self):
        return '(' + str(self.__x) + ', ' + str(self.__y) + ')'


    def __init__(self, x, y):
        self.__x = x
        self.__y = y

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, x):
        self.__x = x


class ChessPieces(object):
    def down_pieces(self, pt):
        """
        :param pt: Point
        :return:
        """
        pass

class WhitePieces(ChessPieces):
    def down_pieces(self, pt):
        print("White Pieces in ", pt)

class BlackPieces(ChessPieces):
    def down_pieces(self, pt):
        print("Black Pieces in ", pt)

class ChessFactory(object):
    __qz = []
    def __init__(self):
        w = WhitePieces()
        ChessFactory.__qz.append(w)
        b = BlackPieces()
        ChessFactory.__qz.append(b)

    def get_chess_point(self, type):
        if(type == 'w'):
            return ChessFactory.__qz[0]
        elif(type == 'b'):
            return ChessFactory.__qz[1]
        else:
            return None

if __name__ == '__main__':
    pt_w = Point(10, 15)
    pt_b = Point(11, 15)
    chess = ChessFactory()
    w = chess.get_chess_point('w')
    b = chess.get_chess_point('b')
    w.down_pieces(pt_w)
    b.down_pieces(pt_b)

Application scenario

The structure and characteristics of the sharing mode are analyzed in the front, and the applicable application scenarios are analyzed in the following. Sharing Mode saves memory space by reducing the number of objects in memory, so the following situations are suitable for sharing mode.

  1. There are a lot of the same or similar objects in the system, which consume a lot of memory resources.
  2. Most objects can be grouped according to internal state, and different parts can be externalized, so that each group only needs to save one internal state.
  3. As the sharing mode needs to maintain an additional data structure to save the sharing elements, it is worth using the sharing mode when there are enough sharing instances.

extend

In the sharing mode described earlier, its structure chart usually contains the parts that can be shared and the parts that cannot be shared. In the actual use process, sometimes it will be slightly changed, that is, there are two special sharing modes: simple sharing mode and composite sharing mode, which are briefly introduced below.

(1) in the simple sharing element mode, all the specific sharing element classes in this sharing element mode can be shared, and there is no non shared specific sharing element class. Its structure is shown in the figure.

(2) composite sharing model. Some sharing objects in this sharing model are composed of simple sharing objects, which are composite sharing objects. Although the composite sharing objects can't be shared by themselves, they can be decomposed into simple sharing objects and shared again. The structure diagram is as shown in the figure.

Topics: Programming