Using vc2005 MFC to realize the example code of dynamically generating the TAB page of the TabCtrl control according to the TreeCtrl

In the example, based on the MFC single document view, click the different sub-ITEM of TreeCtrl to dynamically generate the corresponding TAB page of the TabCtrl control. If some TAB pages have been generated, click the corresponding TreeCtrl sub-item to switch to the generated TAB page, supporting TAB Right-click the page to close the menu, and double-click to close the function.

File: n459.com/file/25127180-479632636 Access password: 551685

The following are irrelevant:

-------------------------------------------Dividing line----- ----------------------------------------

Hello everyone, today we come to understand a new design pattern-the observer pattern.

The idea of ​​the observer mode is very simple, it is widely used in various data monitoring. Many times we want to monitor the changes of a certain data, hoping to take some actions immediately once we learn of the changes. According to the normal operation, we need to open additional threads to monitor. However, it is very troublesome to start the thread, and it needs to bring additional overhead. The observer mode we introduced today can complete this function without unnecessary overhead.

Observer
In the observer mode, the entire run flow is contrary to normal operations. We do not use some programs to monitor data changes. Instead, when the data changes, we notify the corresponding listener that the data has changed. We have also mentioned the benefits before, which can avoid unnecessary expenses.

First, let's implement two listeners. That is, these two listeners will be triggered when the data changes. In this design pattern, the listener is named viewer, and the observation here is not an active observation but a passive notification. Maybe the person who named it can't think of a better name. In fact, I think it should be called receiver better.

class IncreaseViewer:

def __init__(self):
    self.data = 0

def update(self, subject):
    # 判断是否增加
    if subject.data > self.data:
        print('Increased: Subject {} data increased to {}'.format(subject.name, subject.data))
        self.data = subject.data

class DeclineViewer:

def __init__(self):
    self.data = 0

def update(self, subject):
    # 判断是否减少
    if subject.data < self.data:
    print('Decreased: Subject %s data decreased to %d' % (subject.name, subject.data))
    self.data = subject.data


The code of the data observer should be well understood. After understanding the observer class, let's take a look at the data class.

The data class is actually very simple, we only need to design a function so that it can notify the observer when the data is assigned. We all know that in Python, assignment operations cannot be directly perceived, but when the members of the class change, we can use the @property decorator to modify it.

So we use this to implement the data class. If you are familiar with the @property annotation, it is very simple.

class Data(Subject):

def __init__(self, name=''):
    Subject.__init__(self)
    self.name = name
    self._data = 0

@property
def data(self):
    return self._data

@data.setter
def data(self, data):
    self._data = data
    # 关键
    self.notify()

Have you seen the self.notify in the data method? This is the notification function, so when the data member of the Data class changes, we perform the notification operation to notify the observer to execute.

Managing observers
Now that our observers are implemented, we have data classes, and the rest is to connect the two. Of course, we can also implement it simply and rudely in code, but it is better to do a simple management of the connection between the data and the observer. Because different data may require different observers, we cannot make generalizations simply and roughly.

In fact, managing observers does not need to be too complicated, only a simple encapsulation of the list with an object-oriented approach.

class Subject:

def __init__(self):
    self._observer = []

def attach(self, observer):
    if observer not in self._observer:
        self._observer.append(observer)

def detach(self, observer):
    try:
        self._observer.remove(observer)
    except ValueError:
        pass

def notify(self, modifier=None):
    for observer in self._observer:
        if modifier != observer:
            observer.update(self)

Attach means to associate, that is, to associate an observer to the data, detach means to disassociate, and notify is naturally a notification. In fact, it is to use a loop to traverse all the observers, and then execute the corresponding update function.

To simplify the logic here, we made the Subject class the parent class of the Data class. This is equivalent to decoupling the observer and the data to some extent. No matter which part of the logic we modify or optimize in the future, it will not affect the other two parties. The entire code is only 50 lines, which can be said to be very simple, not only for Python, but also for other languages ​​that spend polymorphism, this design pattern is also applicable.

Guess you like

Origin blog.csdn.net/gumenghua_com1/article/details/112824700