Re: make class cluster
Re: make class cluster
- Subject: Re: make class cluster
- From: Sean Murphy <email@hidden>
- Date: Sat, 6 Oct 2007 11:15:12 -0400
On Oct 6, 2007, at 8:10 AM, Hans van der Meer wrote:
I am uncertain how to construct a class-cluster and cannot find all
I should know in the ObjC and Cocoa guides (the montharray example
in the latter is kind of special). Let me describe the setup I have
in mind.
Two classes are to be made, having many methods in common but
differing in the init method and how they produce their result.
Hence the idea of making a class-cluster.
The idea is now:
1. The class-cluster class is merely a dispatcher of the worker
classes.
2. Each of the three classes (cluster class and two work classes)
descends directly from NSObject and thus they are independent classes.
3. The cluster class is called with [[cluster-class alloc] init...]
and dispatches a work class by returning [[work-class alloc] init...]
Questions I could not satisfactorily answer myself:
1. Is the setup of three independent classes correct or should I
make the two work classes a subclass of the cluster class? The
common code can then be shared through the cluster class.
Hey Hans,
I really think your best option is to encapsulate all concrete work
classes and hide them from external use, rather than require that
users of the class cluster possess knowledge of not only the cluster
interface itself but also each subclass interface as well.
Implementing behavior in this manner is consistent with the Abstract
Factory design pattern. An Abstract Factory-based cluster
encapsulates object creation and results in loose coupling because
external code does not depend on a multitude of concrete classes.
External users of your class cluster can be shielded from the fact
that a different object (a subclass of the cluster) is returned
rather than a direct instance of the cluster itself. The way to hide
this fact is by allowing the object to respond to all methods
declared in the cluster's public interface. The goal is to simplify
the external code using the cluster, and encapsulate the actual
determination of which unique subclass to use into one area, the
cluster's init method, rather than having multiple places in your
external code responsible for figuring out which subclass is
appropriate and then creating it. This also makes your code more
maintainable - if you decide another subclass is needed you can
introduce it in only one area, the cluster's init method.
As an example of a class cluster I'm working on for Camino:
We want to parse search plugins, and decided not to couple ourselves
to a certain plugin file format. I made a public, generic, parsing
interface that serves as the class cluster, and then have separate
objects which handle the parsing of each particular format. The
responsibility of determining which subclass to use is moved out of
the client code (which is a maintenance problem because each time we
support a new format we'll need to change all locations of our code
that creates one of these subclasses) and into the cluster itself.
Here's a basic example of what I mean (I threw this together real
quick in Mail, so don't go nuts critiquing it)
// Our Class Cluster's Abstract Interface
@interface SearchPluginParser
- (id)initWithPluginMIMEType:(NSString *)mimeType;
// Abstract method, implemented by private subclasses:
- (BOOL)parsePluginAtURL:(NSUrl *)pluginURL;
// Some accessors:
- (NSURL *)searchPluginURL;
- (NSString *)searchPluginName;
@end
// Private subclass, known only to SearchPluginParser, which it uses
to parse a certain file format:
@interface OpenSearchParser : SearchPluginParser
...
@end
@implementation OpenSearchParser
// Implement those abstract methods in the cluster with the knowledge
of how to parse this unique format.
@end
And, the class cluster (SearchPluginParser) init method:
@implementation SearchPluginParser
// Returns nil if type is not supported.
- (id)initWithPluginMIMEType:(NSString *)mimeType
{
[self release];
// This is where you'd determine which concrete subclass can
best handle the situation
if ([mimeType isEqualToString:kOpenSearchType])
self = [[OpenSearchParser alloc] init];
else
self = nil;
return self;
}
... (define any other default implementations for public methods,
such as the accessors)
@end
----
Externally, the code using the cluster:
- (void)detectedSearchPlugin:(NSDictionary *)searchPluginInfoDict
{
SearchPluginParser *pluginParser = [[SearchPluginParser alloc]
initWithMIMEType:[searchPluginInfoDict
objectForKey:kSearchPluginMIMETypeKey]];
// Check return value and then call methods declared publicly in
SearchPluginParser.h, essentially treating the returned object as a
SearchPluginParser, even though it's actually a subclass of it.
// We know nothing about OpenSearchParser here.
}
The cluster's init method should have the knowledge to determine
which private, concrete subclass to actually implement the required
behavior. Now, if we decide to add another plugin format, the client
code shouldn't need to change at all - the cluster would introduce
the new private subclass and handle the new behavior.
2. In the sequence [[cluster-class alloc] init...] should I release
self? Thus in the cluster-class as init for the production of a
work class:
- (id) init... {
[self release]; // needed??? too early at this point???
id worker = [[worker alloc] init...];
return worker;
}
Yes. See Bill Bumgarner's excellent example at: <http://
www.cocoabuilder.com/archive/message/cocoa/2007/5/25/183673>
I hope this helps,
-Sean
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden