dcsimg
March 31, 2020
Hot Topics:

Working With Design Patterns: Odds and Ends

  • By Jeff Langr
  • Send Email »
  • More Articles »

A specification implementation provides the selection criteria in the isSatisfiedBy method:

public class AuthorSpecification implements Specification {
   private final String author;

   public AuthorSpecification(String author) {
      this.author = author;
   }

   @Override
   public boolean isSatisfiedBy(Holding holding) {
      return author.equals(holding.getBook().getAuthor());
   }
}

Here's another specification implementation that supports selecting by matching book title:

public class TitleSpecification implements Specification {
   private final String title;

   public TitleSpecification(String title) {
      this.title = title;
   }

   @Override
   public boolean isSatisfiedBy(Holding holding) {
      return title.equals(holding.getBook().getTitle());
   }
}

You conceivably could eliminate a bit of redundancy by factoring construction of both of these specifications into a common superclass.

With the specification classes in place, the code in HoldingsAccess simplifies. The single method findBy covers any specification passed to it:

public List<Holding> findBy(Specification specification) {
  List<Holding> results = new ArrayList<Holding>();
  for (Holding holding: getAll())
    if (specification.isSatisfiedBy(holding))
      results.add(holding);
  return results;
}

The HoldingsAccess class is now closed to changes in Holding—adding a new Holding field now requires adding a new Specification implementation. The elimination of impact to HoldingsAccess meets the open-closed principle: Modules should be closed for modification, but open to extension.

Lazy Initialization

Lazy initialization means that you defer initializing a field to a useful value until the time it's first needed. It is a performance optimization.

A library system search returns a list of Book objects. The system presents the user with a list displaying basic book information—author, title, year published, and so on. When the user selects a book for further information, the system shows an image of the front cover of the book. Listing 2 shows an implementation of a Book class that handles loading an image upon construction.

Listing 2: Book.

import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Book {
   private final String author;
   private final String title;
   private final String classification;
   private final String year;
   private BufferedImage coverImage;

   public Book(String author, String title, String classification,
               String year, String imageFilename) {
      this.author = author;
      this.title = title;
      this.classification = classification;
      this.year = year;
      loadCoverImage(imageFilename);
   }

   public String getClassification() {
      return classification;
   }

   public String getAuthor() {
      return author;
   }

   public String getTitle() {
      return title;
   }

   public String getYear() {
      return year;
   }

   @Override
   public String toString() {
      return author + " " + title + " " + year + " " +
         classification;
   }

   public BufferedImage getCoverImage() {
      return coverImage;
   }

   private void loadCoverImage(String imageFilename) {
      try {
         coverImage = ImageIO.read(new File(imageFilename));
      } catch (IOException e) {
         throw new RuntimeException(e);
      }
   }
}




Page 2 of 4



This article was originally published on September 18, 2008

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.


Thanks for your registration, follow us on our social networks to keep up-to-date