设计模式之美:Extension Objects(扩展对象)

 

索引

意图

预期对象的接口将在未来被扩展。通过额外的接口来定义扩展对象。

Anticipate that an object’s interface needs to be extended in the future.

Additional interfaces are defined by extension objects..

结构

参与者

Subject

  • 定义抽象主体对象。其定义用于查询是否包含特定扩展的接口。

Extension

  • 所有扩展类的抽象基类。可以定义负责管理扩展自身的操作。
  • Extension 知道其是谁的扩展。

ConcreteSubject

  • 具体的主体类。实现基类定义的 GetExtension 方法并返回相应的扩展对象。

AbstractExtension

  • 特定种类的扩展类的抽象基类。

ConcreteExtension

  • 继承并实现 AbstractionExtension 类。实现特定的扩展功能。

适用性

当以下情况成立时可以使用 Extension Objects 模式:

  • 当需要为已有对象额外添加全新的或无法预见的接口时。
  • 抽象的主要接口在不同的客户类中拥有不同的角色时。
  • 无法通过子类型化来扩展接口行为时。

效果

  • 扩展对象促进了增加新扩展功能。
  • 类的主要抽象接口不会过于膨胀。
  • 接口的主要抽象在不同的子系统中可实现不同的角色。
  • 客户类变得更加复杂。
  • 需要控制对扩展对象的滥用。

相关模式

  • Visitor模式可以为层级的类结构增加新的行为。Visitor 模式与 Extension Objects 模式拥有类似的益处。相比 Visitor 模式,Extension Objects 模式不需要一个稳固的类层级结构,并且也不引入循环依赖。
  • Decorator模式是另一个可以扩展类的行为的模式。客户类在使用 Decorator 对象时的透明性比使用 Extension Objects 更好。在使用窄接口或需要增强已知接口时更适合使用 Decorator 模式。
  • Adapter模式支持适配一个已知接口。Extension Objects 模式支持附加的接口。当对象需要对扩展接口进行适配时可以同时使用 Extension Objects 模式和 Adapter 模式。

实现

实现方式(一):使用示例结构实现 Extension Objects。

 1 namespace ExtensionObjectsPattern.Implementation1
2 {
3 public abstract class Subject
4 {
5 public abstract void Operation1();
6 public abstract Extension GetExtension(string extensionType);
7 }
8
9 public abstract class Extension
10 {
11 protected Subject _owner;
12
13 public Extension(Subject owner)
14 {
15 _owner = owner;
16 }
17
18 public abstract void DoSomething();
19 }
20
21 public abstract class AbstractExtension : Extension
22 {
23 public AbstractExtension(Subject owner)
24 : base(owner)
25 {
26 }
27 }
28
29 public class ConcreteExtension : AbstractExtension
30 {
31 public ConcreteExtension(Subject owner)
32 : base(owner)
33 {
34 }
35
36 public override void DoSomething()
37 {
38 // do something
39 _owner.Operation1();
40 }
41 }
42
43 public class ConcreteSubject : Subject
44 {
45 private ConcreteExtension _extension;
46
47 public ConcreteSubject()
48 {
49 _extension = new ConcreteExtension(this);
50 }
51
52 public override void Operation1()
53 {
54 // do something
55 }
56
57 public override Extension GetExtension(string extensionType)
58 {
59 if (extensionType == "some type")
60 {
61 return this._extension;
62 }
63
64 return null;
65 }
66 }
67
68 public class Client
69 {
70 public void TestCase1()
71 {
72 Subject subject = new ConcreteSubject();
73 Extension extension = subject.GetExtension("some type");
74 extension.DoSomething();
75 }
76 }
77 }

实现方式(二):使用泛型实现 IExtensibleObject<T> 接口。

 1 namespace ExtensionObjectsPattern.Implementation2
2 {
3 public abstract class Subject : IExtensibleObject<Subject>
4 {
5 public abstract void Operation1();
6 public abstract IEnumerable<IExtension<Subject>> Extensions { get; }
7 }
8
9 public interface IExtensibleObject<T>
10 where T : class, IExtensibleObject<T>
11 {
12 IEnumerable<IExtension<T>> Extensions { get; }
13 }
14
15 public interface IExtension<T>
16 where T : class, IExtensibleObject<T>
17 {
18 void Attach(T owner);
19 void Detach(T owner);
20 }
21
22 public abstract class Extension : IExtension<Subject>
23 {
24 protected List<Subject> _owners;
25
26 public void Attach(Subject owner)
27 {
28 _owners.Add(owner);
29 }
30
31 public void Detach(Subject owner)
32 {
33 _owners.Remove(owner);
34 }
35
36 public abstract void DoSomething();
37 }
38
39 public class ConcreteExtension : Extension
40 {
41 public override void DoSomething()
42 {
43 // do something
44 foreach (var item in _owners)
45 {
46 item.Operation1();
47 }
48 }
49 }
50
51 public class ConcreteSubject : Subject
52 {
53 private List<Extension> _extensions = new List<Extension>();
54
55 public ConcreteSubject()
56 {
57 Extension extension = new ConcreteExtension();
58 extension.Attach(this);
59
60 _extensions.Add(extension);
61 }
62
63 public override void Operation1()
64 {
65 // do something
66 }
67
68 public override IEnumerable<IExtension<Subject>> Extensions
69 {
70 get
71 {
72 return _extensions;
73 }
74 }
75 }
76
77 public class Client
78 {
79 public void TestCase1()
80 {
81 Subject subject = new ConcreteSubject();
82
83 foreach (var extension in subject.Extensions)
84 {
85 (extension as Extension).DoSomething();
86 }
87 }
88 }
89 }

设计模式之美》为 Dennis Gao 发布于博客园的系列文章,任何未经作者本人同意的人为或爬虫转载均为耍流氓。

 
 
绿色通道: 好文要顶 关注我 收藏该文与我联系 

Extension Objects(扩展对象)的更多相关文章

  1. 设计模式之美:Extension Object(扩展对象)

    索引 意图 结构 参与者 适用性 效果 相关模式 实现 实现方式(一):使用示例结构实现 Extension Object. 实现方式(二):使用泛型实现 IExtensibleObject<T ...

  2. 大熊君大话NodeJS之------Global Objects全局对象

    一,开篇分析 在上个章节中我们学习了NodeJS的基础理论知识,对于这些理论知识来说理解是至关重要的,在后续的章节中,我们会对照着官方文档逐步学习里面的各部分模块,好了该是本文主角登台亮相的时候了,G ...

  3. Runtime - Associated Objects (关联对象) 的实现原理

    主要围绕3个方面说明runtime-Associated Objects (关联对象) 1. 使用场景 2.如何使用 3.底层实现 3.1  实现原理 3.2 关联对象被存储在什么地方,是不是存放在被 ...

  4. c# ExpandoObject动态扩展对象

    js中的Object 对象. php中的stdClass. c# 也有动态可扩展对象 ExpandoObject,需要添加System.Dynamic引用 用法: dynamic model = ne ...

  5. JS对象-不可扩展对象、密封对象、冻结对象

    不可扩展对象 Object.preventExtensions() 仅阻止添加自身的属性.但属性仍然可以添加到对象原型. 可以用 Object.isExtensible(obj) 来判断对象是否可扩展 ...

  6. javascript 之 扩展对象 jQuery.extend

    在JQuery的API手册中,extend方法挂载在JQuery 和 JQuery.fn两个不同的对象上,但在JQuery内部代码实现的是相同的,只是功能各不相同. 官方解释: jQuery.exte ...

  7. [C#] Extension Method 扩展方法

    当我们引用第三方的DLL.或者Visual Studio自己的库的时候,或许会发现这样的一个情况,如果这个类型有一个XX的方法就好了.这时候我们可以用到扩展方法,是我们的代码更加灵活和高效. 这里我举 ...

  8. js中使用prototype扩展对象方法

    //---------------------对象 //1. var HomeContrl = function(){ this.foo = 'bar'; //对象方法 this.intro = fu ...

  9. GNOME Shell Extension常用扩展

    这篇博文的,主要目的是为了方便我和大家安装GNOME扩展.我将我安装过的所有扩展列在此处. 常用扩展 Clipboard Indicator https://extensions.gnome.org/ ...

随机推荐

  1. Centos7系统配置上的变化(三)为网络接口添加多IP

    原文 Centos7系统配置上的变化(三)为网络接口添加多IP 实验的方法有 nmtui, 编辑ifcfg-*文件,ip addr 指令,子连接配置文件.一.nmtui手工添加IP 看一下当前网络设备 ...

  2. OCP读书笔记(21) - 题库(ExamA)

    Administer ASM disk groupsBack up the recovery catalogConfigure backup settingsConfigure, Monitor Fl ...

  3. ABP之动态WebAPI

    ABP之动态WebAPI ABP的动态WebApi实现了直接对服务层的调用(其实病没有跨过ApiController,只是将ApiController公共化,对于这一点的处理类似于MVC,对服务端的 ...

  4. python 时间处理

    在实践中,时间处理遇到的问题,需要 Sep 06, 2014 19:30 (UTC 时间) 和 比较当前时间,早晚.知道 此 2014-09-06 19:30 格时间表达式.因此,在处理,通缉 先将s ...

  5. 迷宫的最短路径 (BFS)

    N*M的迷宫,从起点到终点,求最短距离 宽度优先搜索按照距开始状态由近及远的顺序进行搜索,因此可以很容易的用来求最短路径,最少操作之类问题的答案.  (可以构造成pair或者编码成int来表达状态) ...

  6. unity3d NGUI入门(描述和使用插件参数)

    我用NGUI它是3.5.4,Unity3d版本号是4.3.4f需要 NGUI3.5.4 下载NGUI,这是破解版的,用于学习.假设是商用.请支持正版 插件的导入 1.NGUI的导入,双击NGUI Ne ...

  7. 使用php-fpm状态页观察当前的php-fpm状态

    对于php-fpm的參数设置,非常多情况下有这种疑问,就是内置的几个參数比如pm.max_children,pm.start_servers等这几个參数究竟该设置最多为多少才合适.事实上这几个參数往往 ...

  8. 百度地图API显示多个标注点,解决提示信息问题以及给标注增加地图旁的文字连接提示的另一种解决办法

    原文:百度地图API显示多个标注点,解决提示信息问题以及给标注增加地图旁的文字连接提示的另一种解决办法 公司的网站改版要求在一个页面显示百度地图.上面要同时显示很多标注点,标注点当然要有提示信息嘛,提 ...

  9. hibernate 一对多关联关系(具体分析)

    在领域模型中, 类与类之间最普遍的关系就是关联关系. 在 UML 中, 关联是有方向的.  以 Customer 和 Order 为例: 一个用户能发出多个订单, 而一个订单仅仅能属于一个客户. 从 ...

  10. HTML的标签canvas

    定义和使用方法 <canvas> 标签定义图形,比方图表和其它图像. <canvas> 标签仅仅是图形容器,您必须使用脚本来绘制图形. 实例 怎样通过 canvas 元素来显示 ...