Showing posts with label flyweight.. Show all posts
Showing posts with label flyweight.. Show all posts

Friday, November 13, 2015

Factory Class vs. Factory Constructor in Flyweight


Unneeded patterns excite me at least as much as the tried-and-true ones. As I mentioned in the kickoff post for this latest chain, I am eager to explore a modern take on Design Patterns through the lovely lens of Dart.

I was reasonably happy with last night's implementation of the Flyweight pattern. As pointed out to me by the esteemed Matthew Butler, I might be missing some Dart goodness that could clean up my code. Don Olmstead also reported “quite a few style nits looking through your code,” but I'm pretty sure that guy's just crazy (I kid! I'm using dartfmt from now on).

At any rate, Matthew's most interesting suggestion was to convert last night's LampFactory class into a factory constructor. I think he has a valid point. The factory class was responsible for caching the flyweight:
// dartfmt'd -- happy Don? :P
class LampFactory {
  var cache = {};
  Lamp findLamp(color) {
    return cache.putIfAbsent(color, () => new Lamp(color));
  }

  int get totalCount => cache.length;
}
The flyweight class in this simple example described a lamp of varying color:
class Lamp {
  String color;
  Lamp(this.color);
}
Per Matthew's suggestion, I can eliminate the factory class in favor of the Dart factory constructor:
class Lamp {
  String color;
  static Map _cache = {};

  factory Lamp(color) =>
    _cache.putIfAbsent(color, () => new Lamp._(color));

  Lamp._(this.color);

  static int get totalCount => _cache.length;
}
That saves a few lines of code (mostly the class declaration for the factory), but I dunno. The Lamp class seems muddled now that it does two, distinct things. Maybe it is better with the caching code and the “intrinsic lampness” of the flyweight separated:
class Lamp {
  static Map _cache = {};
  static int get totalCount => _cache.length;

  factory Lamp(color) =>
    _cache.putIfAbsent(color, () => new Lamp._(color));

  String color;
  Lamp._(this.color);
}
Were I writing this in real life, I would likely leave it as is. And it does retain the spirit of the flyweight pattern—reducing the number of objects with the same intrinsic properties.. In the spirit of "patterns" however, I remain unsure.

What I do know is that this approach significantly improves the Tree context class. Instead of a bunch of references to factory-this, factory-that:
class Tree {
  int count = 0;
  var _lampFactory;

  Tree() {
    _lampFactory = new LampFactory();
  }

  void hangLamp(color, branchNumber) {
    new TreeBranch(branchNumber)
      ..hang(_lampFactory.findLamp(color));

    count++;
  }

  String get report => "Added ${count} lamps.\n"
      "Used ${_lampFactory.totalCount} kinds of lamps.";
}
The Tree now looks exactly like it would if the flyweight pattern were not in play:
class Tree {
  int count = 0;

  void hangLamp(color, branchNumber) {
    new TreeBranch(branchNumber)
      ..hang(new Lamp(color));

    count++;
  }

  String get report => "Added ${count} lamps.\n"
      "Used ${Lamp.totalCount} kinds of lamps.";
}
That cleanliness seems very much worth a little muddiness in the flyweight class.

In fact, I can use the same approach to convert the TreeBranch class into a flyweight as well—without making a change to the Tree context class:
class TreeBranch {
  static Map _cache = {};
  static int get totalCount => _cache.length;

  factory TreeBranch(number) =>
    _cache.putIfAbsent(number, () => new TreeBranch._(number));

  int number;
  TreeBranch._(this.number);
  // ...
}
Were I to stick with the factory class approach, I would have to introduce more factory objects into the calling context that already seemed lousy with them.

So my preliminary conclusion is that yes, factory constructors do seem of value with the Flyweight pattern in Dart. The ability to implement in-place without changing the context is nice, but I most appreciate the cleanliness of the resulting context code. I have the benefits of the flyweight pattern without the ugliness of factory instance variables polluting things.


Day #2

Thursday, November 12, 2015

Flyweight in Dart


I lack a clear idea what I want Design Patterns in Dart to be. Scholarly like the Gang of Four book? Visually stimulating like Head First Design Patterns? Whimsical? Likely some combination thereof, but until I decide, I explore.

Up tonight, I start with the Flyweight Pattern. It is a simple enough pattern—so simple that it hardly seems a pattern in some languages, but I need to start somewhere. And since the Wikipedia article was kind enough to include a lovely Ruby example, I start tonight by adapting that example into Dart.

The idea behind the Flyweight Pattern is to save storage space via specialized caching. In the Ruby example of decorating a tree with lamps, the goal is to limit the number of lamp objects that are created. After all, there might be hundreds of lamps on larger tree. There is no real value to creating 200 blue lamp objects, 400 green lamp objects, and 300 red lamp objects. The lamps are all the same—only the branch on the tree changes. In GoF terms, the lamp color is an intrinsic property and the branch on which they reside is extrinsic.

Working from the outside, I expect to create a new Tree, hang a bunch of lamps, and then report on it:
main() {
  var tree = new Tree()
    ..hang_lamp('red', 1)
    ..hang_lamp('blue', 1)
    ..hang_lamp('yellow', 1)
    ..hang_lamp('red', 2)
    ..hang_lamp('blue', 2)
    ..hang_lamp('yellow', 2)
    ..hang_lamp('red', 3)
    ..hang_lamp('blue', 3)
    ..hang_lamp('yellow', 3)
    ..hang_lamp('red', 4)
    ..hang_lamp('blue', 4)
    ..hang_lamp('yellow', 4)
    ..hang_lamp('red', 5)
    ..hang_lamp('blue', 5)
    ..hang_lamp('yellow', 5)
    ..hang_lamp('red', 6)
    ..hang_lamp('blue', 6)
    ..hang_lamp('yellow', 6)
    ..hang_lamp('red', 7)
    ..hang_lamp('blue', 7)
    ..hang_lamp('yellow', 7);

  print(tree.report);
}
Dart method cascades work nicely here to hang a bunch of lamps, but still return the original Tree object.

A skeleton of the Tree class might look like:
class Tree {
  int count=0;
  void hang_lamp(color, branch) {
    count++;
  }
  String get report => "Added ${count} lamps.";
}
I will still need to add a Dart equivalent of the LampFactory from the Wikipedia example, but so far, so good. I can report on the total number of lamps that are added to the tree:
Added 21 lamps.
The "flyweight" object will be the Lamp, whose intrinsic property (the color) does not change regardless of where it is placed on the tree. The class definition is wonderfully brief in Dart:
class Lamp {
  String color;
  Lamp(this.color);
}
I never thought I'd say this about Ruby, but the Ruby version from Wikipedia sure is wordy, isn't it?

The LampFactory in Dart is even more terse:
class LampFactory {
  var cache = {};
  Lamp find_lamp(color) {
    return cache.putIfAbsent(color, () => new Lamp(color));
  }
  int get total_number_of_lamps_made => cache.length;
}
The cache is a Map of objects whose key is the color of the lamp. If the color is already present in the cache, then the putIfAbsent() in find_lamp() returns it. If the lamp is not already present, then the second argument to putIfAbsent() is evaluated, added to the cache, and returned. That is a nice example of why I love Dart so much.

Last is the TreeBranch class, which has an associated branch number and needs to know how to hang a lamp:
class TreeBranch {
  int number;
  TreeBranch(this.number);
  void hang(lamp) {
    print("  Hangs ${lamp.color} on branch #${number}.");
  }
}
For now, hanging a lamp just prints to STDOUT a summary of the action.

That pretty much does it for the pattern. Back in the Tree class, I modify the hang_lamp() method to create a TreeBranch on which a factory Lamp can be hung. I also modify the report getter to report on the number of flyweight objects used:
class Tree {
  int count=0;
  var lamp_factory;

  Tree(){ lamp_factory = new LampFactory(); }

  void hang_lamp(color, branch_number) {
    new TreeBranch(branch_number)
      ..hang(lamp_factory.find_lamp(color));

    count++;
  }

  String get report => "Added ${count} lamps.\n"
    "Used ${lamp_factory.total_number_of_lamps_made} kinds of lamps.";
}
With that, I can now report:
Hangs red on branch #1.
  Hangs blue on branch #1.
  Hangs yellow on branch #1.
  Hangs red on branch #2.
  Hangs blue on branch #2.
  Hangs yellow on branch #2.
  Hangs red on branch #3.
  Hangs blue on branch #3.
  Hangs yellow on branch #3.
  Hangs red on branch #4.
  Hangs blue on branch #4.
  Hangs yellow on branch #4.
  Hangs red on branch #5.
  Hangs blue on branch #5.
  Hangs yellow on branch #5.
  Hangs red on branch #6.
  Hangs blue on branch #6.
  Hangs yellow on branch #6.
  Hangs red on branch #7.
  Hangs blue on branch #7.
  Hangs yellow on branch #7.
Added 21 lamps.
Used 3 kinds of lamps.
That was a quick and easy implementation of the Flyweight pattern in Dart. Up tomorrow, I may explore this pattern a little more. For now, this was a good day #1!


Day #1