PDA

View Full Version : help to find OOP correct way


c80609a
10-22-2010, 07:38 AM
hi! :]

I have Container class. Container defines two private objects: Shop and Bag.
Shop class defines _turn() method (next and prev buttons handler).
Bag class contains Pocket object that defines onShopTurnReaction() method.
class Container {
private var _shop:Shop;
private var _bag:Bag;
}

class Shop {
private function _turn():Void { }
}

class Bag {
private var _pocket:Pocket;
}

class Pocket {
public function onShopTurnReaction():Void { }
}
Now, the question is: how can I notify Pocket instance of prev / next buttons clicks?
P.S. I'm asking this because I need to define more OOP correct way for this little task. I will be glad for any suggestions, thanks.

wvxvw
10-22-2010, 11:03 AM
cclass Shop {
private var _handlers:Array/*Function*/;
private function _turn():Void {
for (var o:Object in this._handlers) o();
}
public function addHandler(handler:Funcion/*Void->Void*/):Void {
if (!this._handlers) this._handlers = [];
for (var o:Object in this._handlers) {
if (o == handler) return;
}
this._handlers.push(handler);
}
}
Though, keep in mind, that regarding best practices, it's not OK to keep the functionality of searching inside array in a function that adds a handler, you should put that functionality in a separate function. I was writing the code right here, so wanted to save some time :) I assumed you are using AS2 (not HaXe), anyway, if you are using HaXe, then you'd know how to rewrite the loops, I believe (or just look into HSL project, it provides more robust functionality for this kind of things).

c80609a
10-24-2010, 08:08 AM
Thanks for reply, wvxvw.
As I understand, the approach you've been given means that a Pocket knows about a Shop, isn't it? So I've added an initialization method (_init) to Container and pass _shop through _bag to _pocket. And, finally, _shop.addHandler is used within Pocket class. Look at my code shown below and correct me if i'm wrong:
class Container {
private var _shop:Shop;
private var _bag:Bag;
private function _init():Void {
_bag.shop = _shop;
}
}

class Shop {
private var _handlers:Array;
private function _turn():Void { };
private function _findHandler(func:Object):Function { };
public function addHandler(handler:Function):Void {};
}

class Bag {
private var _pocket:Pocket;
public function set shop(value:Shop):Void {
_pocket.shop = value;
}
}

class Pocket {
private var _shop:Shop;
private function _doSmth():Void {
_shop.addHandler(Delegate.create(this,_onShopTurnR eaction));
}
public function set shop(value:Shop):Void {
_shop = value;
}
private function _onShopTurnReaction():Void { }
}

wvxvw
11-08-2010, 11:56 PM
Terribly sorry for the late reply, not sure you still need it... Well, no, I was talking about something more of observer pattern kind. The goal of observer is to decouple the code parts, and, as such, will lead to better modularity / encapsulation. So, the general idea is that Pocket would signal to whoever is listening, and that listener, in it's turn may signal again to someone else. It is possible to achieve a better anonymity through use of interfaces. Say, and all your objects would implement IObserver interface, then this would happen:
Pocket (can store a reference to any handler and will tell anyone, who had previously subscribed to it, it was stopped).
Bag, still an IObserver, can store a reference to any handler and do the same as Pocket. It will subscribe to Pocket by passing it an onStopTurn method, which pocket will call once it stops.
Shop will have onStopTurn method as well as Container. The container would subscribe to Bag and Shop would subscribe to container, or else, which depends on the Shop role related to Container, the Container may call Shop once it is notified by Bag.
Note, in the first case you can easily remove or replace any link from the chain and yet the rest of the links will remain usable, this is how you ensure encapsulation, and, basically, ensure you write less code :)

import tld.example.utils.ArrayUtils

class tld.example.project.Shop implements IObserver
{
private var _handlers:Array/*Function*/;

public function Shop() { super(); }

/* INTERFACE tld.example.project.IObserver */

public function addHandler(handler:Funcion/*Void->Void*/):Void
{
if (!this._handlers) this._handlers = [];
if (!this.hasHandler(handler)) this._handlers.push(handler);
}

public function removeHandler(handler:Function):Void
{
var position:Number = ArrayUtils.find(handler, this._handlers);
if (position > -1)
this._handlers.splice(position, 1);
}

public function hasHandler(handler:Function):Boolean
{
return ArrayUtils.find(handler, this._handlers) > -1;
}

function signal():Void
{
for (var o:Object in this._handlers) o();
}
}
/**
* ...
* @author wvxvw
*/
interface tld.example.project.IObserver
{
function addHandler(handler:Function/*Void->Void*/):Void;

function removeHandler(handler:Function/*Void->Void*/):Void;

function hasHandler(handler:Function/*Void->Void*/):Boolean;

function signal():Void;
}
/**
* ...
* @author wvxvw
*/
class tld.example.utils.ArrayUtils
{
public function ArrayUtils() { super(); }

public static function find(needle:Object, heystack:Array/*Object*/):Number
{
var result:Number = -1;
var i:Number = 0;
var length:Number = heystack.length;
while (i++ < length)
{
if (heystack[i] === needle)
{
result = i;
break;
}
}
return result;
}
}
I didn't compile it though... it was very long time ago I had to compile AS2... well, but it looks like it should work :)

c80609a
02-18-2011, 07:25 AM
Thanx for reply, wvxvw. Yr answer causes me to meditate upon it, sometimes i am so slowpoke ;]

mac11lover
02-24-2011, 10:05 PM
I am new to Action Script. I use CS3 and need a lot of help.
How do I turn this game I created into an OOP game?