5

我正在寻找抽象一个辅助方法。该方法需要能够接收一个对象,根据对象的类型对其进行处理,并返回一个值。做这样的事情会更好:

interface ICanDo
{
 string DoSomething();
}

string DoThings(ICanDo mything)
{
 return mything.DoSomething();
}

还是做这样的事情更好:

interface IStrategy
{
 string DoSomething(object o);
}

string DoThings(object mything, IStrategy strategy)
{
 return strategy.DoSomething(mything);
}

后者甚至使用策略模式,因为策略没有内置到类中?

有没有更好的方法来做到这一点我没有想到?将策略构建到类中,为任何需要在其上运行 DoThings 的类使用包装器会更好吗?

抱歉——我是这种模式的新手,并试图弄清楚在哪里以及如何最好地使用它。

这就是我最终放在一起的东西。我不确定这是否遵循良好的开发原则。

class IndexWrapper
{
    public interface IDocumentable
    {
        Document BuildDocument();
    }

    public interface IDocumentBuilder
    {
        Type SupportedType { get; }

        Document BuildDocument(object o);
    }

    public class StringDocumentBuilder : IDocumentBuilder
    {
        public Type SupportedType { get { return typeof(string); } }

        public Document BuildDocument(object o)
        {
            Document doc = new Document();
            doc.Add(new Field("string", o as string, Field.Store.YES, Field.Index.ANALYZED));
            return doc;
        }
    }

    public static class IndexableFactory
    {
        public static IDocumentable GetIndexableObject(object o)
        {
            return GetIndexableObject(o, DocumentBuilderFactory.GetBuilder(o));
        }

        public static IDocumentable GetIndexableObject(object o, IDocumentBuilder builder)
        {
            return new IndexableObject(o, builder);
        }
    }

    public static class DocumentBuilderFactory
    {
        private static List<IDocumentBuilder> _builders = new List<IDocumentBuilder>();

        public static IDocumentBuilder GetBuilder(object o)
        {
            if (_builders.Count == 0)
            {
                _builders = Assembly.GetExecutingAssembly()
                                   .GetTypes()
                                   .Where(type => typeof(IDocumentBuilder).IsAssignableFrom(type) && type.IsClass)
                                   .Select(type => Activator.CreateInstance(type))
                                   .Cast<IDocumentBuilder>()
                                   .ToList();
            }

            return _builders.Where(builder => builder.SupportedType.IsAssignableFrom(o.GetType())).FirstOrDefault();
        }
    }

    private class IndexableObject : IDocumentable
    {
        object _o;
        IDocumentBuilder _builder;

        public IndexableObject(object o) : this(o, DocumentBuilderFactory.GetBuilder(o)) { }
        public IndexableObject(object o, IDocumentBuilder builder)
        {
            _o = o;
            _builder = builder;
        }

        virtual public Document BuildDocument()
        {
            return _builder.BuildDocument(_o);
        }
    }
}
4

1 回答 1

4

如有疑问,请牢记 KISS 口头禅——保持简短和简单。模式可能非常有用,但通常它们只在特定情况下有用,否则会增加不必要的复杂性

以我的经验,当你有多个不同的后端可供选择一个类时,策略模式很有用。例如,假设您有一个日志记录类,您的程序使用它来打印调试信息。也许在某些情况下,您想登录到文件。也许您想登录到控制台。也许您甚至想使用您公司制定的专有协议登录到远程服务器!

因此,您的日志记录类可能如下所示:

interface IOutputWriter
{
    void WriteLn(string message);
}

class ConsoleWriter : IOutputWriter
{
    public ConsoleWriter()
    {

    }

    public void WriteLn(string message)
    {
        Console.WriteLine(message);
    }
}

class NetworkWriter : IOutputWriter
{
    public NetworkWriter()
    {

    }

    public void WriteLn(string message)
    {
        //Crazy propietary server protocol action
    }
}

class Logger
{
    IOutputWriter writer;
    public Logger(IOutputWriter writer)
    {
        this.writer = writer;
    }

    public void Log(string message)
    {
        writer.WriteLn(message + "Date");
    }
}

最终结果是您的程序代码如下所示:

class Program
{
    static void Main(string[] args)
    {
        Logger logger = new Logger(new ConsoleWriter());
        logger.Log("Test");
    }
}

好处是,如果你想使用你疯狂的网络协议,你甚至可以在不查看日志类的情况下做到这一点。您只需要使用您的 IOutputWriter 接口创建一个新类并告诉您的记录器使用您的自定义后端。策略模式本质上是定义可重用接口,然后使用这些接口将算法彼此分离。

于 2016-01-26T07:47:09.170 回答