引用链接:http://watirmelon.com/2011/01/24/composition-or-inheritance-for-delegating-page-methods/

Composition or inheritance for delegating page methods?

The thing I like to do when creating a page object pattern for automated web testing is delegating any methods that don’t belong to the Page object itself.

For example, a very simple page object model like this GoogleHomePage doesn’t delegate any methods to the Browser object.

require "rubygems"
require "watir-webdriver" class GoogleHomePage
def initialize(browser)
@browser = browser
end
def visit
@browser.goto "www.google.com"
end
end b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

So, the p.title and p.close statements both fail with an error: undefined method `goto' for # (NoMethodError).

One approach would be simply to write appropriate methods for what you would do on the Browser object. For example:

require "rubygems"
require "watir-webdriver" class GoogleHomePage
def initialize(browser)
@browser = browser
end
def visit
@browser.goto "www.google.com"
end
def title
@browser.title
end
def close
@browser.close
end
end b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

But this isn’t DRY. It means every method of Browser you access to needs to be rewritten. But I often see this happen.

What we should be doing is simply delegating any methods that don’t exist on the Page object to the Browser object which is passed in at initialization. There are two ways I know of to do this: inheritance delegation and composition.

Inheritance Delegation

Inheritance delegation means changing our class so it delegates appropriately using a DelegateClass. This means anything of class Browser is delegated.

For example:

require "rubygems"
require "watir-webdriver" class GoogleHomePage < DelegateClass(Watir::Browser)
def initialize(browser)
super(browser)
end
def visit
self.goto "www.google.com"
end
end b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

From this point forward you don’t need to refer to @browser, instead you just refer to self in your class.

Composition

Composition is about composing the class of different elements, some of which are passed to the browser. This essentially involves creating a method_missing method and passing these methods to the instance variable @browser.

require "rubygems"
require "watir-webdriver" class GoogleHomePage
def initialize(browser)
@browser = browser
end
def method_missing(sym, *args, &block)
@browser.send sym, *args, &block
end
def visit
@browser.goto "www.google.com"
end
end b = Watir::Browser.new :firefox
p = GoogleHomePage.new b
p.visit
puts p.title
p.close

This means that any reference to the Browser object still needs to refer to @browser throughout the class.

Inheritance or Composition?

You can see from the examples above, both approaches are very similar, but from researching these, it seems that most people prefer composition to inheritance in ruby, mainly due to maintainability of class chains. In our example, the inheritance chain is small and very simple, so I don’t think this poses a great maintainability issue.

Composition or inheritance for delegating page methods?的更多相关文章

  1. 组合优于继承 Composition over inheritance

    https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance 解答1 Prefer composition ...

  2. Effective Java 16 Favor composition over inheritance

    Inheritance disadvantage Unlike method invocation, inheritance violates encapsulation. Since you don ...

  3. React之Composition Vs inheritance 组合Vs继承

    React的组合   composition: props有个特殊属性,children,组件可以通过props.children拿到所有包含在内的子元素, 当组件内有子元素时,组件属性上的child ...

  4. Inheritance setUp() and tearDown() methods from Classsetup() and Classteardown

      I have a general test class in my nosetests suit and some sub-classes, inheriting from it. The con ...

  5. selenium page object model

    Page Object Model (POM) & Page Factory in Selenium: Ultimate Guide 来源:http://www.guru99.com/page ...

  6. <Effective C++>读书摘要--Inheritance and Object-Oriented Design<二>

    <Item 36> Never redefine an inherited non-virtual function 1.如下代码通过不同指针调用同一个对象的同一个函数会产生不同的行为Th ...

  7. inheritance in kentico

    Visual inheritance http://devnet.kentico.com/docs/7_0/devguide/index.html?visual_inheritance.htm The ...

  8. Thinking in Java——笔记(17)

    Containers in Depth Full container taxonomy You can usually ignore any class that begins with " ...

  9. 静态工厂方法VS构造器

    我之前已经介绍过关于构建者模式(Builder Pattern)的一些内容,它是一种很有用的模式用于实例化包含几个属性(可选的)的类,带来的好处是更容易读.写及维护客户端代码.今天,我将继续介绍对象创 ...

随机推荐

  1. C# 播放音乐

    用 .NET 自带的类库 System.Media 下面的 SoundPlayer 来播放音乐的方式,此种方式使用托管代码,应该是更为可取的方式吧 使用起来非常简单,下面稍作说明: . 支持同步.异步 ...

  2. linux命令-tar打包和压缩并用

    tar在打包的时候进行压缩 支持 gzip bzip2 xz 格式 -z  gzip格式 -j  bzip2格式 -J  xz格式 压缩打包 [root@wangshaojun ~]# tar -zc ...

  3. javaIO 流分析总结

    Java中的流,可以从不同的角度进行分类. 按照数据流的方向不同可以分为:输入流和输出流. 按照处理数据单位不同可以分为:字节流和字符流. 按照实现功能不同可以分为:节点流和处理流. 输出流: 输入流 ...

  4. DBVisualizer Pro for mac

    公司使用的是DB2数据库,支持DB2的数据库客户端常用的有DBeaver和DBVisualizer.DBeaver是免费的,但本人电脑安装后,启动一直报错,问题一直没解决就放弃了.改用DBVisual ...

  5. Entity Framework Code-First(4):Simple Code First Example

    Simple Code First Example: Let's assume that we want to create a simple application for XYZ School. ...

  6. LINQ中的陷阱--TakeWhile&SkipWhile

    在用TakeWhile,SkipWhile设置陷阱之前,我们先来看一看他们的兄弟Take和Skip: public static IEnumerable<T> Take<T>( ...

  7. Spring入门第三十课

    基于XML的方式配置事务 直接看代码: package logan.study.spring.tx.xml; public interface BookShopDao { //根据书号获取书的单价 p ...

  8. webpack@3.6.0(1) -- 快速开始

    本篇内容 前言 配置入口和输出 热更新 loader配置 js代码压缩 html的打包与发布 前言 //全局安装 npm install -g webpack(3.6.0) npm init //安装 ...

  9. java工具类学习整理——集合

    好久没有总结一些东西了,同时集合部分的知识点也学习的比较早了,但是从来没有抽时间去研究和学习,今天正好有时间就总结一下map常用的遍历方法: package runningwhile; import ...

  10. ubuntu 安装 mysql 5.7 简记

    安装: apt-get install mysql-server 会安装最新版本的 mysql ,安装时会提示输入 root 的密码 进入 mysql: mysql -u root -p 进入后会出现 ...