首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >策略模式还是接口?

策略模式还是接口?
EN

Stack Overflow用户
提问于 2013-02-25 14:06:31
回答 1查看 2.4K关注 0票数 4

我希望抽象一个帮助器方法。该方法需要能够接受对象,根据对象的类型对其执行操作,并返回一个值。这样做会不会更好:

代码语言:javascript
复制
interface ICanDo
{
 string DoSomething();
}

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

或者这样做更好:

代码语言:javascript
复制
interface IStrategy
{
 string DoSomething(object o);
}

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

后者是否使用了策略模式,因为策略没有被构建到类中?

有没有更好的方法来做这件事,我没有想到?将策略构建到类中,对任何需要在其上运行DoThings的类使用包装器,是不是更好?

对不起--我是这个模式的新手,正在尝试找出在哪里以及如何最好地使用它。

这就是我最终拼凑出来的。我不确定这是否遵循了良好的开发原则。

代码语言:javascript
复制
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);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-26 15:47:09

当你不确定的时候,把接吻咒语记在你的脑海里--保持简短和简单。模式可能非常有用,但它们通常只在特定情况下有用,否则会增加不必要的复杂性

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

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

代码语言:javascript
复制
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");
    }
}

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

代码语言:javascript
复制
class Program
{
    static void Main(string[] args)
    {
        Logger logger = new Logger(new ConsoleWriter());
        logger.Log("Test");
    }
}

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

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15061053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档