- let's look at a real world use of Observer: maintaining an application log.
- subject: org.moock.logger.Logger (extends org.moock.util.Observable)
- observers: org.moock.logger.OutputWindowView, org.moock.logger.TextFieldView (implement org.moock.util.Observer)
- infoObj: LogMessage
- org.moock.logger.Logger source code:
// PACKAGE
AsSetupPackage("org.moock.logger");
// CLASS Logger EXTENDS org.moock.util.Observable
/**
* A general log class. Use getLog() to create an app-wide instance.
* Send messages with fatal(), error(), warn(), info(), and debug().
* Add views for the log with addObserver() (views must implement Observer).
*
* @version 1.0.0
*/
org.moock.logger.Logger = function () {
// Show "INFO" level messages by default.
this.setLevel("INFO");
}
// SET SUPERCLASS
org.moock.logger.Logger.prototype = new org.moock.util.Observable();
// STATIC PROPERTIES
// A reference to the log instance (Singleton).
org.moock.logger.Logger.log = null;
// The valid severity levels for logged messages.
org.moock.logger.Logger.logLevels = ["FATAL",
"ERROR",
"WARN",
"INFO",
"DEBUG"];
// INSTANCE PROPERTIES
// The zero-relative filter level for the log.
// Messages with a level above logLevel will
// not be passed on to observers.
// Default is 3, "INFO" (only DEBUG messages are filtered out.
org.moock.logger.Logger.prototype.logLevel = null;
// STATIC METHODS
/**
* Returns a reference to the log instance.
* If no log instance exists yet, creates one.
*/
org.moock.logger.Logger.getLog = function () {
if (org.moock.logger.Logger.log == null) {
org.moock.logger.Logger.log = new org.moock.logger.Logger();
}
return org.moock.logger.Logger.log;
}
// INSTANCE METHODS
/**
* Sets the message filter level for the log.
*
* @param l The level above which messages are filtered out.
*/
org.moock.logger.Logger.prototype.setLevel = function (l) {
// Find the specified level in the logLevel array.
for (var i = 0; i < org.moock.logger.Logger.logLevels.length; i++) {
if (org.moock.logger.Logger.logLevels[i].toLowerCase() == l.toLowerCase()) {
// Found the human-readable level, now set it as an integer.
this.logLevel = i;
this.info("Log level set to: " + org.moock.logger.Logger.logLevels[i]);
// We found the log level, so quit looking.
return;
}
}
// No log level by the specified name was found.
this.warn("Invalid log level specified.");
}
/**
* Returns the human-readable message filter level for the log.
*/
org.moock.logger.Logger.prototype.getLevel = function () {
return org.moock.logger.Logger.logLevels[this.logLevel];
}
/**
* Sends a message to the log, with severity "FATAL".
*/
org.moock.logger.Logger.prototype.fatal = function (msg) {
// If the filter level is at least "FATAL", then
// broadcast the message to observers.
if (this.logLevel >= 0) {
// Construct the log message object.
var lm = new org.moock.logger.LogMessage(msg, "FATAL");
// Pass the message on to observers.
this.setChanged();
this.notifyObservers(lm);
}
}
/**
* Sends a message to the log, with severity "ERROR".
*/
org.moock.logger.Logger.prototype.error = function (msg) {
// If the filter level is at least "ERROR", then
// broadcast the message to observers.
if (this.logLevel >= 1) {
var lm = new org.moock.logger.LogMessage(msg, "ERROR");
this.setChanged();
this.notifyObservers(lm);
}
}
/**
* Sends a message to the log, with severity "WARN".
*/
org.moock.logger.Logger.prototype.warn = function (msg) {
// If the filter level is at least "WARN", then
// broadcast the message to observers.
if (this.logLevel >= 2) {
var lm = new org.moock.logger.LogMessage(msg, "WARN");
this.setChanged();
this.notifyObservers(lm);
}
}
/**
* Sends a message to the log, with severity "INFO".
*/
org.moock.logger.Logger.prototype.info = function (msg) {
// If the filter level is at least "INFO", then
// broadcast the message to observers.
if (this.logLevel >= 3) {
var lm = new org.moock.logger.LogMessage(msg, "INFO");
this.setChanged();
this.notifyObservers(lm);
}
}
/**
* Sends a message to the log, with severity "DEBUG".
*/
org.moock.logger.Logger.prototype.debug = function (msg) {
// If the filter level is at least "DEBUG", then
// broadcast the message to observers.
if (this.logLevel >= 4) {
var lm = new org.moock.logger.LogMessage(msg, "DEBUG");
this.setChanged();
this.notifyObservers(lm);
}
}
- org.moock.logger.LogMessage source code:
// PACKAGE
AsSetupPackage("org.moock.logger");
// CLASS LogMessage
/**
* A log message. Sent by the the Logger to all registered log observers
* when a new log message is generated.
*/
org.moock.logger.LogMessage = function (m, l) {
this.setMessage(m);
this.setLevel(l);
}
// PROPERTIES
// The actual message sent to the log.
org.moock.logger.LogMessage.prototype.msg = null;
// The severity level of this message (one of: "FATAL", "ERROR",
// "WARN", "INFO", "DEBUG");
org.moock.logger.LogMessage.prototype.lev = null;
// METHODS
/**
* Sets the log message.
*/
org.moock.logger.LogMessage.prototype.setMessage = function (m) {
this.msg = m;
}
/**
* Returns the log message.
*/
org.moock.logger.LogMessage.prototype.getMessage = function () {
return this.msg;
}
/**
* Sets the severity level for this message.
*/
org.moock.logger.LogMessage.prototype.setLevel = function (l) {
this.lev = l;
}
/**
* Returns the severity level for this message.
*/
org.moock.logger.LogMessage.prototype.getLevel = function () {
return this.lev;
}
- org.moock.OutputWindowView source code:
// PACKAGE
AsSetupPackage("org.moock.logger");
// CLASS OutputWindowView IMPLEMENTS org.moock.util.Observer
/**
* An observer of the Logger class. When a movie is played in
* the Flash authoring tool's Test Movie mode, this class displays
* messages sent to the log in the Output window.
*/
org.moock.logger.OutputWindowView = function (l) {
this.log_model = l;
}
// PROPERTIES
// The log that this object is observing.
org.moock.logger.OutputWindowView.prototype.log_model = null;
// METHODS
/**
* Invoked when the log changes. For details, see the
* Observer interface.
*/
org.moock.logger.OutputWindowView.prototype.update = function (o, infoObj) {
trace(infoObj.getLevel() + ": " + infoObj.getMessage());
}
- org.moock.TextFieldView source code:
// PACKAGE
AsSetupPackage("org.moock.logger");
// CLASS TextFieldView IMPLEMENTS org.moock.util.Observer
/**
* An observer of the Logger class. This class displays
* messages sent to the log in a text field.
*/
org.moock.logger.TextFieldView = function (l,
target,
depth,
x,
y,
w,
h) {
this.log_model = l;
this.target = target;
this.makeTextField(this.target, depth, x, y, w, h);
}
// PROPERTIES
// The log that this object is observing.
org.moock.logger.TextFieldView.prototype.log_model = null;
// The movie clip in which the text field will be created.
org.moock.logger.TextFieldView.prototype.target = null;
// A reference to the text field.
org.moock.logger.TextFieldView.prototype.out = null;
// METHODS
/**
* Invoked when the log changes. For details, see the
* Observer interface.
*/
org.moock.logger.TextFieldView.prototype.update = function (o, infoObj) {
// Display the log message in the log text field.
this.out.text += infoObj.getLevel() + ": " + infoObj.getMessage() + "\n";
// Scroll to the bottom of the log text field.
this.out.scroll = this.out.maxscroll;
}
/**
* Creates a text field in the specified movie clip at
* the specified depth. Log messages are displayed in the text field.
*/
org.moock.logger.TextFieldView.prototype.makeTextField = function (target,
depth,
x,
y,
w,
h) {
// Create the text field.
this.target.createTextField("log_txt", depth, x, y, w, h);
// Store a reference to the text field.
this.out = this.target.log_txt;
// Put a border on the text field.
this.out.border = true;
// Make the text in the text field wrap.
this.out.wordWrap = true;
}
- example usage (source code in logDemo.fla):
#include "../org/moock/lang/AsSetupPackage.as"
#include "../org/moock/util/Observable.as"
#include "../org/moock/logger/Logger.as"
#include "../org/moock/logger/LogMessage.as"
#include "../org/moock/logger/OutputWindowView.as"
#include "../org/moock/logger/TextFieldView.as"
// Grab a reference to the log.
var log = org.moock.logger.Logger.getLog();
// Create log observers.
var outputWinLog = new org.moock.logger.OutputWindowView(log);
log.addObserver(outputWinLog);
var textLog = new org.moock.logger.TextFieldView(log, this, 0, 100, 100, 300, 200);
log.addObserver(textLog);
// This won't display because the log
// severity level is set to "INFO".
log.debug("Testing...");
// Try the levels that are allowed by severity level "INFO".
log.info("Log started.");
log.warn("This is a test warning.");
log.error("This is a test error.");
log.fatal("This is a test fatal error notification.");
// Now tell the log to display messages with
// severity of "DEBUG".
log.setLevel("DEBUG");
log.debug("Testing..."); // Works now!