小话设计模式(番外一)插件模式

插件(Plugin)模式向用户提供了一种扩展程序的接口,用户可以在程序本体之外,按照指定接口编写插件来为程序增加功能。

可能实际开发中不太会运用到插件模式,但是它确实我们经常会使用到的一种模式。例如CocosBuilder和Unity3D都不同程度的提供了插件功能,用户可以自己编写插件来完善或者定制编辑器。此外,我们也可以编写Visual Studio、XCode或Eclipse的插件来扩展这些IDE。

插件模式中会有一个管理器用来管理这些插件,而如何调用插件的方法?这里我们就需要制定一个接口,插件必须实现接口方法,而管理器则调用这些方法。

插件抽象类:

public abstract class Plugin{
	public virtual void DoSomeThing ()
	{
	}
}


如何知道插件的类型并实例化它们呢?我们可以使用反射(参考C#语法小知识(十)反射)+配置文件的方法来解决这个问题。

插件管理器:

public static class PluginManager
{
	private static Dictionary _plugins = new Dictionary();
	public static void LoadPlugin(string assemblyName, string typeStr)
	{
		string key = assemblyName + typeStr;
		if (_plugins.ContainsKey (key)) {
			return;
		}
		var oh = System.Activator.CreateInstance (assemblyName, typeStr);
		object instance = oh.Unwrap ();
		_plugins [key] = (Plugin)instance;
	}
	public static void UnloadPlugin(string assemblyName, string typeStr)
	{
		string key = assemblyName + typeStr;
		if (_plugins.ContainsKey (key)) {
			_plugins.Remove (key);
		}
	}
	public static void UnloadAllPlugins()
	{
		_plugins.Clear ();
	}
	public static void RunPlugins()
	{
		foreach (var kv in _plugins) {
			kv.Value.DoSomeThing ();
		}
	}
}


(示例中没有实现读取文件并加载插件的方法,需要根据实际情况来编写具体代码)

我们可以编写一个dll文件,并且添加测试插件:

public class TestPlugin : Plugin
{
	public override void DoSomeThing ()
	{
		Console.WriteLine ("Test plugin");
	}
}


测试:

		PluginManager.LoadPlugin ("xxx.dll", "TestPlugin");
		PluginManager.RunPlugins ();


当然这种模式并不限于程序外开发,程序内开发我们也可以考虑使用这种模式。这样就与IOS里的NotificationCenter有些类似(观察者+单例,参考小话设计模式(十七)观察者模式),只不过插件管理器与事件发布者(示例中没有实现,可以认为测试代码中RunPlugins这个方法就是发布了一个事件)耦合度会更紧密一些。当然如果没有必要的话,尽量还是不要使用反射了。


插件模式的好处:

1、提供了扩展程序的可能。

2、将插件与事件发布者的耦合集中到插件管理器当中去,事件发布者并不需要知道插件中的具体逻辑,只负责发送事件。

3、增加插件也很方便

缺点在于,使用插件模式扩展程序,往往需要使用反射,这样就会影响程序的执行速度。


你可能感兴趣的:(设计模式,小话设计模式)