Using the Factory Method Pattern in PHP 5, a Quick Example

Place your factory classes & interface inside a directory of your choice, like /api/YOUR-PATH-TO-CLASSES-HERE/. Just make sure to specify that path in the __autoload() method when you use the factory (see the last code example below).

Set up the Interface

<?
interface IApiGrabr
{
	public function callApi();
}
?>

Implement the Interface with a Twitter Class

This code assumes there’s a directory named ‘api’ at your server’s public root folder. Also, note, in a live example you might want to have a separate file to store some of your Twitter, etc credentials. The Twitter oAuth library I’m using can be found on github.

<?
class TwitterApiGrabr implements IApiGrabr 
{
	public function callApi(){

		require_once('/api/twitteroauth.php'); //open source class from github

		$connection = new TwitterOAuth('your-consumer-key', 
		                               'your-consumer-secret', 
		                               'your-access-token-here',
		                               'your-access-token-secret-here');

		$content = $connection->get('account/rate_limit_status');
		
		// you can now call all the methods on the twitteroauth/connection object
		$user = $connection->get('account/verify_credentials');

		$favs = $connection->get('favorites',  array(
			  'screen_name'      => 'TechCrunch',
			  'count'            => 11,
		));

		//this is FPO, in real life write some formatted display code:
                var_dump($favs);
	}
}
?>

Implement the Interface with an Instagram Class

The below code uses a handy open source Instagram oAuth class from github.

<?
class InstagramApiGrabr implements IApiGrabr 
{
	public function callApi(){

		//open source class from github
		require_once('/api/Instagram.php'); 

		$instagram = new Instagram('your-client-id-here', 'your-client-secret-here', 'your-access-token-here');
		
		//simplified call, in real life, there should be an authentication check (see Instagram.php example on github)		  
	    try {
	        $instafeed = $instagram->get('users/self/media/liked'); 
	    }catch(InstagramApiError $e) {
	        die($e->getMessage());
	    }
		
	    //FPO JSON display, in real life, you'd format this w/ HTML, probably via a for loop	
        echo '<p>&nbsp;</p>'.json_encode($instafeed);
	}
}
?>

Implement the Interface with a Tumblr Class

<?
class TumblrApiGrabr implements IApiGrabr 
{
	public function callApi(){
		//posts
		$pth2 = 'http://api.tumblr.com/v2/blog/YOUR-TUMBLR-NAME-HERE.tumblr.com/posts/photo?api_key=YOUR-API-KEY-HERE';	

		///Tumblr account's posts - http://www.tumblr.com/docs/en/api/v2#posts
		$pthresult2 = file_get_contents($pth2);
		
		//FPO to just display raw JSON response, in real life, you'd format it with HTML
		echo $pthresult2;	
	}
}
?>

Set up your Factory class

<?
class MyFactory
{ 
  private static $dictionary;

  public static function init()
    {
      self::$dictionary = array('instagram' => new InstagramApiGrabr(), 
                         'twitter' => new TwitterApiGrabr(), 
                         'tumblr' => new TumblrApiGrabr());
    }

    public static function GetApi($param='instagram')
    {
        return self::$dictionary[$param]; 
    } 
}
?>

Use Your Factory Class Like So

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>API Test</title>
</head>
<body>
<?
  //allow PHP to auto include your individual class files as needed 
  function __autoload($class_name) {
      require_once('/api/YOUR-PATH-TO-CLASSES-HERE/'.$class_name . '.php');
  }
  
  MyFactory::init();

  /// control the below factory method calls via drop down menu, page navigation inside a carousel, etc. 

  //will spit out the Instagram JSON feed
  $a = MyFactory::GetApi('instagram');
  $a->callApi(); 

  //will spit out the Twitter JSON feed
  $a = MyFactory::GetApi('twitter');
  $a->callApi();

  //will spit out the Tumblr JSON feed
  $a = MyFactory::GetApi('tumblr');
  $a->callApi();
?>
</body>
</html>

Side Note on the Code Igniter framework and PHP interfaces

The Code Igniter mvc framework for PHP doesn’t seem to support “interface” or “implements” key words as of version 2.1.3.

Advertisements

Javascript Animation Example Using requestAnimFrame, Basic Trigonometry & HTML5 Canvas – Part 3

Updating previous version to remove the use of “new function()” from the JS code.

Alternate JS version, without classical inheritance

The original code works fine but it feels weird to be using classical inheritance in a prototypal language – “new function” inside “TIMSHAYA.Triganimation = new function()”. Below is version of the JS code that removes “new function” and replaces it with “function()”, adding a “return” statement that in turn exposes the public “init” method, while maintaining closure (inner function init()’s access to it’s external function’s private members like “numsqr”, “drawRect()” & “animate()”).

KEEP IN MIND: using the “new function” version might turn out to be faster in some cases as far as performance goes. In this case, jsPerf shows that Chrome 16 is the only browser where “new function” is faster than the inline version (unless I’m screwing up the test somehow).

Note: Don’t forget to define requestAnimFrame (see HTML file here).

var TIMSHAYA   = TIMSHAYA || {}; //create your own namespace 

(function(whichCanvas){ 

   TIMSHAYA.Triganimation = function(){     
            var numsqr = 40;
            var mShapes = [];   
            var canvas = document.getElementById(whichCanvas);
            var context = canvas.getContext("2d");    

            function drawRect(myRect)
            {            
                context.beginPath();
                context.rect(myRect.x, myRect.y, myRect.width, myRect.height);
                
                context.fillStyle = "#8ED6FF";
                context.fill();
                context.lineWidth = myRect.borderWidth;
                context.strokeStyle = "black";
                context.stroke();
            }

            function animate(lastTime, mShapes, animProp)
            {
                if (animProp.animate) 
                {            
                    var date = new Date();
                    var time = date.getTime();
                    var timeDiff = time - lastTime;

                    for(var j = 0; j < numsqr; j++)
                    {
                        mShapes[j].x = mShapes[j].centerX + Math.cos( mShapes[j].angle * Math.PI/180 ) * mShapes[j].radius;   
                        mShapes[j].y = mShapes[j].centerY + Math.sin( mShapes[j].angle * Math.PI/180 ) * mShapes[j].radius; 

                        (mShapes[j].angle < 360) ? mShapes[j].angle += 1 : mShapes[j].angle = 0;      
                    }                            
                    lastTime = time;
                    
                    // clear canvas
                    context.clearRect(0, 0, canvas.width, canvas.height);
                    
                    // draw                    
                    for(var l = 0; l < numsqr; l++)
                       drawRect(mShapes[l]);                    
                    
                    // request new frame
                    requestAnimFrame(function(){
                        animate(lastTime,  mShapes, animProp);
                    })
                }
            }
         
            return {
                init: function() {           
                        
                         for(var i = 0; i < numsqr; i++)
                         {                     
                             mShapes[i] = {
                                angle:0,
                                width:20,
                                height:20,
                                x: 100 + i*10,
                                y: 270,
                                centerX: 290,
                                centerY: 290,      
                                radius: 250 - (1 + i * 5),            
                                borderWidth: 1
                            }
                         }
                     
                        var animProp = {
                            animate: false
                        }
                      
                        document.getElementById(whichCanvas).addEventListener("click", function(){
                            if (animProp.animate) {
                                animProp.animate = false;
                            }
                            else {
                                animProp.animate = true;
                                var date = new Date();
                                var time = date.getTime();
                                animate(time,  mShapes, animProp);
                            }
                        })
                      
                        for(var k = 0; k < numsqr; k++)
                           drawRect( mShapes[k] );                                   
                    
                }    
            };        

    }(); 
 
    TIMSHAYA.Triganimation.init();

})("myCanvas");

Using Interfaces with Display List Objects in AS3.0

This is an example illustration of Option 2 from a great post by Mr. Wright.

Project structure:

Create an interface to be implemented by your group of display objects. In this case it’s called IEmployee, since I’ll be using it to call an identically named method on three employees (Developer, Designer, Project Manager):

package com.interfaces
{
	import com.interfaces.ISprite;
	
	public interface IEmployee extends ISprite
	{
		function talk():String;
	}
}

Create an ISprite (or IMovieClip, or IDisplayObjet) interface, since one doesn’t exist in AS3:

package com.interfaces
{
	import flash.display.Sprite;
	
	public interface ISprite
	{
		function get view():Sprite;	
	}
}

Each of the concrete classes below – Developer, Designer, ProjectManager – contains identically named methods “view” & “talk()” which can be called by a user class which doesn’t have to know exactly which class’s instance it’s calling.

Developer class implements IEmployee:

package com.view
{
	import com.interfaces.IEmployee;
	
	import flash.display.Sprite;
	
	public class Developer extends Sprite implements IEmployee
	{
		public function Developer()
		{
			super();
		}
	
		public function get view():Sprite
		{
			return this as Sprite;
		}

		public function talk():String
		{
			return "Code, code, code! Why are the PSD layers not organized? Code, code code!";
		}
	}
}

Designer class also implements IEmployee:

package com.view
{
	import com.interfaces.IEmployee;
	
	import flash.display.Sprite;
	
	public class Designer extends Sprite implements IEmployee
	{
		public function Designer()
		{
			super();
		}
		
		public function get view():Sprite
		{
			return this as Sprite;
		}
		
		public function talk():String
		{
			return "Pantone! CMYK! RGB! What the hell is HEX? Vector Smart Object!";
		}
	}
}

and ProjectManager class implements IEmployee as well:

package com.view
{
	import com.interfaces.IEmployee;
	
	import flash.display.Sprite;
	
	public class ProjectManager extends Sprite implements IEmployee
	{
		public function ProjectManager()
		{
			super();
		}
		
		public function get view():Sprite
		{
			return this as Sprite;
		}
		
		public function talk():String
		{
			return "Meeting! Do you need an LCD spec? Meeting! Can I get an ETA on that? Meeting, meeting.";
		}
	}
}

This is a basic user class, which randomly specifies which employee to use and calls the talk() method on that employee:

package
{
	import com.interfaces.IEmployee;
	import com.view.Designer;
	import com.view.Developer;
	import com.view.ProjectManager;
	
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.utils.getQualifiedClassName;
	
	[SWF (width="964", height="655", backgroundColor="#000000", frameRate="30")]	
	public class DisplayListPolyMorphismByInterface extends Sprite
	{
		private var worker:IEmployee;
		private var employees:Array = [new Developer(), 
                                       new Designer(), 
                                       new ProjectManager()];
		
		public function DisplayListPolyMorphismByInterface()
		{
			initApp();				
		}		
		
		public function initApp():void
		{
			stage.addEventListener(MouseEvent.MOUSE_UP, changeWorker, false, 0, true); 			 
			addWorker();					
		}	
		
		public function addWorker():void 
		{
			worker = employees[ randomInt(0,2) ] as IEmployee;		 			
			addChild( worker.view );
			
			talkTheTalk();			
		}
		
		public function changeWorker(e:MouseEvent):void
		{				
			removeChild( worker.view );
			worker = null; 
			
			addWorker();
		}

		public function talkTheTalk():void 
		{
			trace( "This employee is a " + getQualifiedClassName(worker.view) + " and says '" + worker.talk() + "'" );
		}
		
		public function randomInt(low:Number=0, high:Number=1):int
		{
			return Math.floor(Math.random() * (1+high-low)) + low;
		}				
	}
}

Robotlegs with LoaderMax’s XMLLoader

This is a quick modification of hubflanger’s useful Robotlegs AS3.0 Site tutorial. I’m expanding her service class to use a content loading library called LoaderMax.

Since she built hers via an interface, there’s no need to refactor the existing class. Instead use her ISiteDataService interface and create a similar class called LoaderMaxDataService, like so:

package com.hubflanger.robotlegsdemo.service
{
	import com.hubflanger.robotlegsdemo.model.vo.SectionVO;
	import com.hubflanger.robotlegsdemo.model.SiteModel;
	import com.hubflanger.robotlegsdemo.events.SystemEvent;
	
	import com.greensock.events.LoaderEvent;
	import com.greensock.loading.LoaderMax;
	import com.greensock.loading.XMLLoader;
	
	import flash.events.Event;
	import flash.net.*;
	
	import org.robotlegs.mvcs.Actor;
		
	/**
	 * A Service class that handles loading and parsing of the site's xml data.
	 */	
	public class LoaderMaxDataService extends Actor implements ISiteDataService
	{
		/**
		 * Inject the <code>SiteModel</code> Singleton.
		 */		
		[Inject]
		public var model				:SiteModel; 
		
		//private var queue				:LoaderMax; 		

		public function LoaderMaxDataService()
		{ 			
			LoaderMax.activate([XMLLoader]);					
		}
				
		public function loadData():void 
		{			
			var xml:XMLLoader = new XMLLoader("assets/data.xml", 
											  {name:"mainXML", 
											  onComplete:loadCompleteHandler, 
											  estimatedBytes:4000});
			xml.load();						
		}
		
		/**
		 * Handler for the XMLLoader's onComplete.
		 * <p>
		 * Parses the xml data and stores the <code>SectionVO</code> objects in 
		 * the <code>SiteModel</code> Singleton.
		 * <p>
		 * Dispatches a <code>SystemEvent.INIT_VIEW</code> event.
		 * 
		 * @param event
		 */		
		private function loadCompleteHandler(e:LoaderEvent):void 
		{			
			var xml:XMLLoader = e.target as XMLLoader; 
			
			model.header = xml.content.header.text(); 
			var sections:XMLList = xml.content.sections.section; 
			
			for each (var section:XML in sections) 
			{
				var sectionVO:SectionVO = new SectionVO(section.@id,
														section.label.toString(),
														section.content.toString());				
				
				model.sectionsList.push(sectionVO);
				model.sectionsHash[sectionVO.id] = sectionVO;
			}			
			
			model.defaultSection = model.sectionsList[0].id;
			
			dispatch(new SystemEvent(SystemEvent.INIT_VIEW, false));					
		}
	}
}

Update 1 line in the ApplicationContext from this:

 
injector.mapClass(ISiteDataService, SiteDataService);

to this:

 
injector.mapClass(ISiteDataService, LoaderMaxDataService);

There’s no need to update the LoadDataCommand to use LoaderMaxDataService, instead of SiteDataService. hubflanger & Robotlegs’ (ISiteDataService) use of polymorphism allows this to continue working unaltered:

package com.hubflanger.robotlegsdemo.controller
{
	import com.hubflanger.robotlegsdemo.service.ISiteDataService;
	
	import org.robotlegs.mvcs.Command;
	
	/**
	 * Responds to the <code>ContextEvent.STARTUP_COMPLETE</code> framework event.
	 */	
	public class LoadDataCommand extends Command
	{
		/**
		 * Creates an instance of SiteDataService via dependency injection.
		 */		
		[Inject]
		public var siteDataService:ISiteDataService;
		
		/**
		 * Calls the loadData() method of the SiteDataService instance.
		 */		
		override public function execute():void
		{
			siteDataService.loadData();
		}
	}
}

Note to self: “@protocol” in Objective-C is like an implementable “interface” in AS3.0 or Java

Here’s a quick example. Perhaps, before trying to decipher the grey code boxes, scroll down a bit to this section:

  • The protocol specification is quite simple. it is basically @protocol ProtocolName (methods you must implement) @end.
  • To conform to a protocol, you put the protocols you’re conforming to in <>’s, and comma separate them. Example: @interface SomeClass <Protocol1, Protocol2, Protocol3>

Basic Tabbed-Menu / View Stack Flex App Structure

Just some quick notes on setting up a basic Flex app that encapsulates individual page content (views). This could work for a multi-tab widget or a simple microsite.

Here’re some ways to interact w/ the View Stack:

Simple ViewStack switching by id
Selecting a view in a ViewStack just by its Class

To replace the views with your own custom .mxml files, check out at least the first 7 minutes of the Cairngorm Part 2 video here. It ends up looking like this:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:view="view.*" 
    layout="vertical" >

//....
<mx:ViewStack id="yourID" width="100%" height="100%">
<view:YourPage1 />
<view:YourPage2 />
</mx:ViewStack>
//...

Note, the extra namespace at the top, “xmlns:view”, and make sure that directory actually exists in your source folder. The “view” directory is where YourPage1.mxml and YourPage2.mxml should be stored.

Note to self: Structs in C++ are like Value Objects in Actionscript or Java

Wiser folks than I have accurately pointed out that no analogy is perfect. In this case, it’s plain to see that Structs in C++ are an official data type that’s part of the language itself, whereas Value Objects are more of a convention (former design pattern[1]) created by Java programmers (among others) over the years.

Structs are similar to Value Objects since both are essentially containers for a bunch of data. Both don’t have methods. Perhaps, Value Objects could have Getters & Setters, but more often there aren’t methods.

An example of a Struct in a C++ tutorial:

struct database {
  int id_number;
  int age;
  float salary;
};

int main()
{
  database employee;  
  employee.age = 22;
  employee.id_number = 1;
  employee.salary = 12000.21;
}

An example of a Value Object from an AS3 tutorial using PureMVC:

package com.flashtuts.model.vo
{
	public class DataVO
	{
		public var dataURL:String          = 'assets/xml/data.xml';
		public var urlsArray:Array	  = [ ];
		public var urlsDataArray:Array  = [ ];
	}
}

1. In Java the Value Object Pattern is now called the Transfer Object Pattern.