Python構築プラグインフレームワーク(コンポーネント開発ベース)-伊壬さんのブログから転載

6409 ワード

コンセプト
コンポーネントベースの開発(Component-Based Development、略称CBD)はソフトウェア開発のモデルである.これは現在のソフトウェア多重化理論の実用化の研究のホットスポットであり、コンポーネントオブジェクトモデルのサポートの下で、既存のコンポーネントを多重化することによって、ソフトウェア開発者は「プラグアンドプレイ」でアプリケーションソフトウェアを迅速に構築することができる.
メリット
  • 柔軟性が高い:各機能モジュール間の結合が低く、各コンポーネントは独立しており、プラグインフレームワーク全体に付着して実行され、実際の実装はロードされ、無視されない.
  • は多重性が強い:コンポーネント間の通信またはインタラクションは、プラグインフレームワークによって提供されるインタフェースによって実行されるため、各コンポーネントの見解は依存逆転の原則を遵守する.したがって,どのモジュールの機能が必要であっても,そのプラグインを直接多重化するだけでよい.

  • フレームワークの説明
                。             ,        ,        ,   A     :        ,       ,       ,      。    B     :        ,       ,       ,      ……,              ,    ,     ,        。
    
         ,                                 ,          ,       。   A,  B           ,          ,              ,         。              ,                   ,          。
    

    インプリメンテーション
                    Python                 ,           ,       。    ,    。
    

    ディレクトリ構造
    ++PluginFrame
    – main.py
    – PluginManager
    ++ Plugins
    -- Plugin1.py
    
    -- Plugin2.py
    
    -- Plugin3.py
    
    -- Plugin4.py
    
    
    ###      
    import os
    import sys
    from imp import find_module
    from imp import load_module
    
    class PluginManager(type):
        #          
        __PluginPath = 'Plugins'
    
        #        
        def __init__(self,name,bases,dict):
            if not hasattr(self,'AllPlugins'):
                self.__AllPlugins = {}
            else:
                self.RegisterAllPlugin(self)
    
        #      
        @staticmethod
        def SetPluginPath(path):
            if os.path.isdir(path):
                PluginManager.__PluginPath = path
            else:
                print '%s is not a valid path' % path
    
        #              ,         
        @staticmethod
        def LoadAllPlugin():
            pluginPath = PluginManager.__PluginPath
            if not os.path.isdir(pluginPath):
                raise EnvironmentError,'%s is not a directory' % pluginPath
    
            items = os.listdir(pluginPath)
            for item in items:
                if os.path.isdir(os.path.join(pluginPath,item)):
                    PluginManager.__PluginPath = os.path.join(pluginPath,item)
                    PluginManager.LoadAllPlugin()
                else:
                    if item.endswith('.py') and item != '__init__.py':
                        moduleName = item[:-3]
                        if moduleName not in sys.modules:
                            fileHandle, filePath,dect = find_module(moduleName,[pluginPath])
                        try:
                            moduleObj = load_module(moduleName,fileHandle,filePath,dect)
                        finally:
                            if fileHandle : fileHandle.close()
    
        #       
        @property
        def AllPlugins(self):
            return self.__AllPlugins
    
        #    
        def RegisterAllPlugin(self,aPlugin):
            pluginName = '.'.join([aPlugin.__module__,aPlugin.__name__])
            pluginObj = aPlugin()
            self.__AllPlugins[pluginName] = pluginObj
    
        #    
        def UnregisterPlugin(self,pLuginName):
            if pluginName in self.__AllPlugins:
                pluginObj = self.__AllPlugins[pluginName]
                del pluginObj
    
        #      。
        def GetPluginObject(self, pluginName = None):
            if pluginName is None:
                return self.__AllPlugins.values()
            else:
                result = self.__AllPlugins[pluginName] if pluginName in self.__AllPlugins else None
                return result
    
        #      ,      。(         )
        @staticmethod
        def GetPluginByName(pluginName):
            if pluginName is None:
                return None
            else:
                for SingleModel in __ALLMODEL__:
                    plugin = SingleModel.GetPluginObject(pluginName)
                    if plugin:
                        return plugin
    
    #        。        。            ,  Python metaclass   ,     。                     。
    class Model_Component(object):
        __metaclass__ = PluginManager
    
        def Start(self):
            print 'Please write the Start() function'
    
        def ChangeLanguage(self,language):
            print 'Please write the ChangeLanguage() function'
    
    class Model_MenuObj(object):
        __metaclass__ = PluginManager
    
        def Start(self):
            print 'Please write the Start() function'
    
        def ChangeLanguage(self,language):
            print 'Please write the ChangeLanguage() function'
    
    class Model_ToolBarObj(object):
        __metaclass__ = PluginManager
    
        def Start(self):
            print 'Please write the Start() function'
    
        def ChangeLanguage(self,language):
            print 'Please write the ChangeLanguage() function'
    
    class Model_ParamPanelObj(object):
        __metaclass__ = PluginManager
    
        def Start(self):
            print 'Please write the Start() function'
    
        def ChangeLanguage(self,language):
            print 'Please write the ChangeLanguage() function'
    
    __ALLMODEL__ = (Model_ParamPanelObj,Model_ToolBarObj,Model_MenuObj,Model_Component)
    
    #  1
    from PluginManager import Model_MenuObj
    
    class Plugin1(Model_MenuObj):
        def __init__(self):
            pass
    
        #        
        def Start(self):
            print "I am plugin1 , I am a menu!"
    
    #  2
    from PluginManager import Model_ToolBarObj
    
    class Plugin2(Model_ToolBarObj):
        def __init__(self):
            pass
    
        def Start(self):
            print "I am plugin2 , I am a ToolBar!"
    
    #  3
    from PluginManager import Model_ParamPanelObj
    
    class Plugin3(Model_ParamPanelObj):
        def __init__(self):
            pass
    
        def Start(self):
            print "I am plugin3 , I am a ParamPanel!"
    
    #  4
    from PluginManager import Model_Component
    
    class Plugin4(Model_Component):
        def __init__(self):
            pass
    
        def Start(self):
            print "I am plugin4 , I am a Component!"
    
    #main  
    
    import sys
    from PluginManager import PluginManager
    from PluginManager import __ALLMODEL__
    
    if __name__ == '__main__':
        #      
        PluginManager.LoadAllPlugin()
    
        #             
        for SingleModel in __ALLMODEL__:
            plugins = SingleModel.GetPluginObject()
            for item in plugins:
    
                #          
                item.Start()
    

    しゅつりょく
    I am plugin3 , I am a ParamPanel!
    I am plugin2 , I am a ToolBar!
    I am plugin1 , I am a menu!
    I am plugin4 , I am a Component!