Skip to content

Latest commit

 

History

History
284 lines (163 loc) · 9.91 KB

File metadata and controls

284 lines (163 loc) · 9.91 KB

Behavioral Patterns Pt.1

Learning Objectives

By the end of this lesson, you should be able to...

  1. Describe:
    • the Chain-of-Responsibility and Command patterns
    • the software problem each is intended to solve
    • potential use cases for each (when to use them)
  2. Assess:
    • the suitability of a given design pattern to solve a given problem
    • the trade offs (pros/cons) inherent in each
  3. Implement basic examples of both patterns explored in this class

Initial Exercise

Part 1 - Individually

  • A Quiz on last class content & after class section

Behavioral Patterns

In software engineering, Behavioral design patterns are design patterns that identify common communication patterns between objects.

By doing so, these patterns increase flexibility in carrying out such communications.

Though there are many more to explore, we will focus on these two key Behavioral patterns in this lesson:

  • Chain-of-Responsibility (CoR)
  • Command

Chain-of-Responsibility

CoR

refactoring guru

The Chain-of-Responsibility pattern is a behavioral design pattern that allows an event to be processed by one of many handlers.

It consists of a source of command objects and a series of processing objects.

Each processing object contains logic that defines the types of command objects that it can handle; the rest are passed to the next processing object in the chain.

Source: wikipedia.org

example

refactoring guru

Problems Addressed

There are several objects that can handle a request but only one of them should be used.

How to Implement

You define a chain of receiver objects having the responsibility, depending on run-time conditions, to either handle a request or forward it to the next receiver on the chain (if any).

This enables sending a request to a chain of receivers without having to know which one handles the request.

The request gets passed along the chain until a receiver handles the request. The sender of a request is no longer coupled to a particular receiver.

Example of CoR

Link to Example

Key Example Use Case

The Cocoa and Cocoa Touch frameworks actively use the chain-of-responsibility pattern for handling events.

Objects that participate in the chain are called responder objects, inheriting from the UIResponder (iOS) class.

All view objects (UIView), view controller objects (UIViewController), window objects (UIWindow), and the application object (UIApplication) are responder objects

Typically, when a view receives an event it can’t handle, it dispatches it to its superview until it reaches the view controller or window object.

If the window can’t handle the event, the event is dispatched to the application object, which is the last object in the chain.

Apple_responder_chain_graphic

Source: Apple, Inc.

Question: When should you use it?

Chain of responsibility - Activity

25 min Follow this activity in groups of 2 or 3.

10 min Walkthrough solution

Command

restaurant

refactoring guru

Command is a design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time.

This information includes the method name, the object that owns the method and values for the method parameters

It turns a request/action into a stand-alone object that contains all information about the request.

This transformation lets you parameterize methods with different requests, delay or queue a request’s execution, and support undoable operations.

It involves three component types:

  • The invoker stores and executes commands.

  • The command encapsulates the action as an object.

  • The receiver is the object acted upon by the command.

Problems Addressed

It should be possible to configure an object (that invokes a request) with a request.

Implementing (hard-wiring) a request directly into a class is inflexible because it couples the class to a particular request at compile-time, which makes it impossible to specify a request at run-time.

Benefits

  • Single Responsibility Principle.
  • Open/Closed Principle. (Introduce new commands into the app without breaking existing code)
  • You can implement undo/redo.
  • You can implement deferred execution of operations.
  • You can assemble a set of simple commands into a complex one.

When to use it?

  • When you want to parametrize objects with operations.
  • When you want to queue operations, schedule their execution, or execute them remotely.
  • When you want to implement reversible operations.

The most well-known use of this pattern:

In some strategy games, the ability to rollback moves the user did not like is an essential user experience feature. The command pattern simplifies the implementation of Undo and Redo user actions.

Command Pattern - Activity

Follow this activity

After Class

  1. The other Behavioral Patterns in the links below
  2. Research the following concepts:
  • The Composite Pattern
  • UndoManager (in Foundation framework)
  • UIEvent Objects
  • Touch Objects
  • All Touch Events (e.g., touchesEnded(_:_:))
  • the hitTest(_:With:) function

Stretch Challenge Using Apple's Media Player framework, implement a simple (i.e., basic UI only) iPhone app that will play, pause, and restart (skip to beginning) the following sample file (or any video/audio file of your choice):

https://devimages-cdn.apple.com/samplecode/avfoundationMedia/AVFoundationQueuePlayer_HLS2/master.m3u8

Archived activity CoR (But you can try it out)

Additional Resources

  1. Behavioral Patterns - an article
  2. Behavioral pattern - wikipedia
  3. Chain-of-Responsibility - wikipedia
  4. Command pattern - wikipedia
  5. Intermediate Design Patterns in Swift - Ray Wenderlich
  1. Using Responders and the Responder Chain to Handle Events - from Apple
  2. Design Patterns in Swift: Chain of Responsibility Pattern - an article
  3. Refactoring guru - Chain
  4. Refactoring guru - Command
  5. Gang Of Four Cheat Sheet

For The More Curious

  1. Using the Debug View Hierarchy tool on this simple example reveals little of the powerful utility this tool can have in analyzing your code.
  • TODO: To understand more of how this tool can be used, experiment with it on some of your actual projects that have more complex UI architectures.
  1. Apple has long provided ways to analyze view hierarchies. In addition to the Debug View Hierarchy tool, there have been several command-line debugging phrases which can be used to analyze the view hierarchy of your app during runtime.

One example: You can return information about the state of your current view hierarchy by setting a breakpoint and executing the following command in your debug pane:

expr -l objc++ -O -- [UIViewController _printHierarchy]

The output from this command can provide information useful in debugging your views:

special_po_command_for_views