·············@my-deja.com writes:
> What's the usual way to implement the state pattern (from "Design
> Patterns" book) in CLOS? O:-)
To quote from the implementation section of said book (page 309):
<quote>
4. Using dynamic inheritance. Changing the behaviour for a particular
request could be accomplished by changing the object's class at
run-time, but this is not possible in most object-oriented
programming languages. Exceptions include Self [US87] and other
delegation-based languages that provide such a mechanism and hence
support the State pattern directly.
</quote>
CLOS is not a delegation-based language, but it does support
changing the class of an object directly, via change-class. Here a
short excerpt from MaiSQL, where all open database connections are
sub-classes of the class database, which get turned into
closed-database objects upon disconnection:
(defclass database ()
((name :initarg :name :reader database-name))
(:documentation
"This class is the supertype of all databases handled by MaiSQL."))
(defclass closed-database ()
((name :initarg :name :reader database-name))
(:documentation
"This class represents all databases after they are closed via
`disconnect'."))
(defun query (query-expression &key (database *default-database*))
"Execute the SQL query expression query-expression on the given database.
Returns a list of lists of values of the result of that expression."
(database-query query-expression database))
(defgeneric database-query (query-expression database)
(:method (query-expression (database closed-database))
(declare (ignore query-expression))
(signal-closed-database-error database))
(:documentation "Internal generic implementation of query."))
(defun disconnect (&key (database *default-database*))
"Closes the connection to database. Resets *default-database* if that
database was disconnected and only one other connection exists."
(when (database-disconnect database)
(setq *connected-databases* (delete database *connected-databases*))
(when (eq database *default-database*)
(setq *default-database* (car *connected-databases*)))
(change-class database 'closed-database)
t))
(defgeneric database-disconnect (database)
(:method ((database closed-database))
(signal-closed-database-error database))
(:documentation "Internal generic implementation of disconnect."))
Regs, Pierre.
--
Pierre R. Mai <····@acm.org> http://www.pmsf.de/pmai/
The most likely way for the world to be destroyed, most experts agree,
is by accident. That's where we come in; we're computer professionals.
We cause accidents. -- Nathaniel Borenstein