[Design Pattern] Substitute Interface

目的

将对象的成员建立为替身接口的成员,用来解耦对象之间的循环相依。

情景

假设开发人员接手一个系统,在系统里有订单对象、送货物件,其中订单对象使用送货物件所提供的送货方法。

当系统继续设计下去,会发现送货方法需要订单对象的相关信息才能决定如何送货。例如说:送货方法需要商品数量,来决定要派卡车送货还是要派机车送货;送货方法需要商品价格来决定要用盒子包还是要用纸袋包。当送货方法的逻辑越来越复杂的时候,最终就会发现送货方法需要订单对象的所有成员才能满足送货方法的运算需求。

送货方法需要订单对象的所有成员,很直觉的设计就是将订单对象作为送货方法的参数,用以提供订单对象的所有成员来满足送货方法的运算需求。系统设计到了这个阶段,就会发现订单对象使用送货物件、而送货物件也使用了订单对象,这也就是产生了对象之间循环相依的问题。(在.NET中,对象之间的循环相依是能够通过编译、并且执行的设计)

为了解决对象之间循环相依的问题,回过头思考订单对象、送货物件之间的关系。会发现在送货物件的送货方法中,其实需要的是订单对象的「所有成员」,而不是真的需要一个订单对象。

这时开发人员可以将订单对象的所有成员,建立为一个「替身接口」并且让订单对象来继承这个接口,用来透过替身接口来提供订单对象的所有成员。接着送货物件中的送货方法,改为使用这个替身接口做为参数,这样就可以取得订单对象的所有成员,而不需要将订单对象作为送货方法的参数。也就是说经由这样的设计,让订单对象、送货物件都改为相依于替身接口,进而就解除了订单对象、送货物件之间循环相依的问题。

结构

参与者

Substitute

  • 提供Primary对象的所有成员。

Primary

  • 实作Substitute界面。
  • 持有Secondary对象的参考。
  • 将本身视为Substitute接口来做为Secondary对象的函式参数,用以提供所有成员。

Secondary

  • 使用Substitute接口做为函式参数,来取得Primary对象的所有成员。

合作方式

实作

  • 类别图

  • IOrder

    public interface IOrder
    {
    // Properties
    int Quantity { get; set; } int Amount { get; set; } // Methods
    void Deliver();
    }
  • Order

    public class Order : IOrder
    {
    // Fields
    private readonly Deliverer _deliverer = new Deliverer(); // Properties
    public int Quantity{get; set;} public int Amount { get; set; } // Methods
    public void Deliver()
    {
    _deliverer.Deliver(this);
    }
    }
  • Deliverer

    public class Deliverer
    {
    // Methods
    public void Deliver(IOrder order)
    {
    // Print
    Console.WriteLine(order.Quantity);
    Console.WriteLine(order.Amount);
    }
    }
  • Program

    class Program
    {
    static void Main(string[] args)
    {
    // Test
    var order = new Order();
    order.Quantity = 12345;
    order.Amount = 67890;
    order.Deliver(); // End
    Console.WriteLine("End...");
    Console.ReadLine();
    }
    }
  • 执行结果

下载

范例程序代码:点此下载

[Design Pattern] Substitute Interface的更多相关文章

  1. [转]Design Pattern Interview Questions - Part 4

    Bridge Pattern, Composite Pattern, Decorator Pattern, Facade Pattern, COR Pattern, Proxy Pattern, te ...

  2. [转]Design Pattern Interview Questions - Part 2

    Interpeter , Iterator , Mediator , Memento and Observer design patterns. (I) what is Interpreter pat ...

  3. [转]Design Pattern Interview Questions - Part 3

    State, Stratergy, Visitor Adapter and fly weight design pattern from interview perspective. (I) Can ...

  4. [转]Design Pattern Interview Questions - Part 1

    Factory, Abstract factory, prototype pattern (B) What are design patterns? (A) Can you explain facto ...

  5. 为什么要提倡“Design Pattern呢

    为什么要提倡“Design Pattern呢?根本原因是为了代码复用,增加可维护性. 那么怎么才能实现代码复用呢?面向对象有几个原则:开闭原则(Open Closed Principle,OCP).里 ...

  6. design pattern及其使用

    什么是设计模式? design pattern是一个通用的,可以被重用的关于一个常见的问题的解决方案. 为什么要用设计模式? 引入设计模式的理论基础非常简单.我们每天都会碰到问题.我们可能碰到决定使用 ...

  7. Asp.Net Design Pattern Studynotes -- Part1

    Asp.Net Design Pattern Studynotes -- Part1 let's start with an exampleto entry amazing OO world ! le ...

  8. [Design Pattern] Service Locator Pattern 简单案例

    Service Locator Pattern,即服务定位模式,用于定位不同的服务.考虑到 InitialContext::lookup 的成本比较高,提供了 Cache 类缓存以定位到的服务. 代码 ...

  9. [Design Pattern] Factory Pattern 简单案例

    Factory Pattern , 即工厂模式,用于创建对象的场景,属于创建类的设计模式 . 下面是一个工厂模式案例. Shape 作为接口, Circle, Square, Rectangle 作为 ...

随机推荐

  1. IIS7/IIS7.5 二级域名伪静态设置方法

    转载地址:http://www.admin5.com/article/20120107/402582.shtml

  2. ArchLinux 下架设PPTPD VPN服务

    直接上命令吧: 安装: pacman -Sy pacman -S pptpd 配置: vim /etc/pptpd.conf option /etc/ppp/options.pptpd stimeou ...

  3. C++ string 用法详解

    /////////////////////////////////////////////////////////////////////////////////// 任何人对本文进行引用都要标明作者 ...

  4. oracle rac理解和用途扩展

    Oracle RAC的优势在于利用多个节点(数据库实例)组成一个数据库,这样在保证了数据库高可用性的情况下更充分的利用了多个主机的性能,而且可以通过增加节点进行性能的扩展.实现Oracle RAC需要 ...

  5. unix/linux中图形界面那些事

    我们知道unix/linux刚开始的时候是没有图形界面的,随着时代的发展,排版.制图.多媒体应用越来越普遍了,这些需求都需要用到图形界面(Graphical User Interface).为此,MI ...

  6. php和egret的配合

    egret对资源路径和js的应用都是相对路径,而在现在许多流行的框架里,一般都把js和资源放到专门的文件夹下,如public. 修改步骤: 1.修改index.html,改为全路径,如: <sc ...

  7. Web开发入门疑问收集(不定期更新)

    bootstrap container和container-fluid的区别 原始链接 container 根据显示设备满足的最小宽度,来决定实际内容宽度,是一个根据设置内容阶梯式响应的布局. 例子: ...

  8. DataTables 入门使用

    前言简述 DataTables是一个JavaScript类库,它操作HTML表格,改变表格CSS样式,增强表格功能使其更具有交互性. DataTables依赖于JQuery类库. 入门示例 环境:Da ...

  9. bootstrap插件学习-bootstrap.alert.js

    我们先看bootstrap.alert.js的结构 var dismiss = '[data-dismiss="alert"]' //自定义属性 Alert = function ...

  10. 企业云部署要如何选择IaaS PaaS和SaaS

    1为什么IaaS成了灵丹妙药   我非常惊讶,为什么很多传统企业已经接受了云计算,但接受的方式却往往不尽人意.对大多数企业来说,云计算的投入产出比相对较小,并且局限于基础设施层的环节. 就目前而言,大 ...