Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有效地使用Decorator模式_C#_Design Patterns_Architecture_Decorator - Fatal编程技术网

C# 有效地使用Decorator模式

C# 有效地使用Decorator模式,c#,design-patterns,architecture,decorator,C#,Design Patterns,Architecture,Decorator,我正在设计一个库,提供对我们公司使用的Bug跟踪器应用程序的访问 目前,我们只需要访问简单的功能: 开放性缺陷 查询缺陷(按给定条件搜索) 连接/断开与Bug跟踪器的连接 我设计该库是为了提供这些操作的接口,以便在新版本出现时可以透明地替换实现 为了支持未来更多的运营,我们可以: 扩展接口;使所有实现类实现添加的成员 使用Decorator模式在运行时添加操作/功能 问题是——Decorator似乎与底层基类/接口联系太紧密。 我的意思是,它依赖于这样一个事实,即它所修饰的对象提供了足够的访问权

我正在设计一个库,提供对我们公司使用的Bug跟踪器应用程序的访问

目前,我们只需要访问简单的功能:

  • 开放性缺陷
  • 查询缺陷(按给定条件搜索)
  • 连接/断开与Bug跟踪器的连接
  • 我设计该库是为了提供这些操作的接口,以便在新版本出现时可以透明地替换实现

    为了支持未来更多的运营,我们可以:

  • 扩展接口;使所有实现类实现添加的成员
  • 使用Decorator模式在运行时添加操作/功能
  • 问题是——Decorator似乎与底层基类/接口联系太紧密。 我的意思是,它依赖于这样一个事实,即它所修饰的对象提供了足够的访问权限,使它能够轻松地添加操作

    在本例中,如果我不在我的界面中公开为bug追踪器提供API的底层第三方对象,装饰器将无法添加更多操作

    如何通过更好地设计来克服这个问题?

    您不需要装饰图案 decorator模式在这个场景中不是很有用。它的目的是允许您在运行时附加行为。您试图在编译时附加行为(或多或少)

    见:

    此模式允许用户创建以下类型的代码实例:

    • 故意未修饰的类型,仅具有基本行为
    • 允许您提供重写行为的任意修饰类型
    为此,它会产生大量的设计开销。对于一个装饰,您需要实现四个类

    如果您不关心如何实例化有意未修饰的类型,那么这将是很大的开销

    你可能根本不需要担心这个 如果您已经推出了一个接口,我只会担心这种情况,同时重新部署所有内容(客户机和服务)的成本会很高。如果您可以同时重新部署整个世界,那么对于所有用户,只需修改界面即可

    多个接口更适合您的场景 如果您只是想在交错展开时保持服务和客户端的运行,我建议您利用.Net允许对接口进行多重继承的事实,并对接口进行版本设置

    发布修改接口的新版本时,添加一个新接口并实现这两个功能。使您的对象实现这两个接口

    这将允许您错开卷展栏并保持向后兼容。您可以在任何对日程安排最有意义的时间弃用和删除旧接口

    这里有一个例子。请注意,我根本没有想到服务的设计,除了解决您的具体问题:

    namespace Version1
    {
        public interface IOpenDefectService
        {
            void Submit(string title, string description, int severity);
            void Bump(int issueId);
        }
    }
    
    namespace Version2
    {
        public interface IOpenDefectService
        {
            void Submit(string title, string description, int severity);
    
            // Removed Bump method - it was a bad idea
    
            // Added an optional priority field
            void Submit(string title, string description, int severity,
                int priority);
    
            // Added support for deleting 
            void Delete(int id);
        }
    }
    
    public class OpenDefectService : Version1.IOpenDefectService,
        Version2.IOpenDefectService
    {
        // Still must support it until you no longer have any clients using it.
        // Here to support staggered rollouts
        [Obsolete("This method is deprecated.  Don't use it")]
        public void Bump(int issueId) { /* Still has implementation... */ }
    
        public void Submit(string title, string description,
            int severity) { /* ... */ }
        public void Submit(string title, string description,
            int severity, int priority) { /* ... */ }
        public void Delete(int id) { /* ... */ }
    }
    
    你不需要装饰图案 decorator模式在这个场景中不是很有用。它的目的是允许您在运行时附加行为。您试图在编译时附加行为(或多或少)

    见:

    此模式允许用户创建以下类型的代码实例:

    • 故意未修饰的类型,仅具有基本行为
    • 允许您提供重写行为的任意修饰类型
    为此,它会产生大量的设计开销。对于一个装饰,您需要实现四个类

    如果您不关心如何实例化有意未修饰的类型,那么这将是很大的开销

    你可能根本不需要担心这个 如果您已经推出了一个接口,我只会担心这种情况,同时重新部署所有内容(客户机和服务)的成本会很高。如果您可以同时重新部署整个世界,那么对于所有用户,只需修改界面即可

    多个接口更适合您的场景 如果您只是想在交错展开时保持服务和客户端的运行,我建议您利用.Net允许对接口进行多重继承的事实,并对接口进行版本设置

    发布修改接口的新版本时,添加一个新接口并实现这两个功能。使您的对象实现这两个接口

    这将允许您错开卷展栏并保持向后兼容。您可以在任何对日程安排最有意义的时间弃用和删除旧接口

    这里有一个例子。请注意,我根本没有想到服务的设计,除了解决您的具体问题:

    namespace Version1
    {
        public interface IOpenDefectService
        {
            void Submit(string title, string description, int severity);
            void Bump(int issueId);
        }
    }
    
    namespace Version2
    {
        public interface IOpenDefectService
        {
            void Submit(string title, string description, int severity);
    
            // Removed Bump method - it was a bad idea
    
            // Added an optional priority field
            void Submit(string title, string description, int severity,
                int priority);
    
            // Added support for deleting 
            void Delete(int id);
        }
    }
    
    public class OpenDefectService : Version1.IOpenDefectService,
        Version2.IOpenDefectService
    {
        // Still must support it until you no longer have any clients using it.
        // Here to support staggered rollouts
        [Obsolete("This method is deprecated.  Don't use it")]
        public void Bump(int issueId) { /* Still has implementation... */ }
    
        public void Submit(string title, string description,
            int severity) { /* ... */ }
        public void Submit(string title, string description,
            int severity, int priority) { /* ... */ }
        public void Delete(int id) { /* ... */ }
    }
    

    我还没有部署任何接口。部分问题是第一个接口需要支持多少(我很确定基本的操作集可能就足够了)。为什么我需要引入一个新的接口而不是更新现有的接口?另外,您能否给出一个例子来说明运行时和编译时行为的不同。这个答案是:“为了支持将来更多的操作”。“我还没有部署任何接口”-那么您就不需要引入新的接口或新的装饰器。只需更改您的界面:)我的意思是-我将使用包含2-3个操作的简化界面发布此文件,但在更新此文件以支持未来几个月/年的更多操作时,希望将工作量减至最少。@liortal:最基本的工作(如果您可以立即重新部署整个内容)是编辑您的界面。如果你是你唯一的消费者,你不需要保持向后兼容,你可以一次性更换整个应用程序。我还没有部署任何界面。部分问题是第一个接口需要支持多少(我很确定基本的操作集可能就足够了)。