Working With Design Patterns: State California

The state pattern can help simplify complex conditional logic by representing individual states as classes, each with its own simple behavior.

Local Companies

cellphoneonly.com
310-257-9043
1801 W. Lomita Bl.
Lomita, CA
etelligence technologies inc.
626-810-9262
17700 castleton st. #383
city of industry, CA
Apacheta Corporation
858-674-1166
11440 West Bernardo Ct.
San Diego, CA
Strategix Performance, Inc.
(801) 363-7267
1280 Bison West
Newport Beach, CA
Astoundit Software, LLC
805-492-2506
1534 N. Moorpark Rd
Thousand Oaks, CA
UTS Global LLC
408-496-4234
390 Reed Street
Santa Clara, CA
DigitalHousing & Administration, LLC
626.440.9030.111
101 E. Green St. suite 5
Pasadena, CA
Paycurement, Inc.
760-200-4911
73140 HWY. 111 suite 5
Palm Desert, CA
Zoomerang
800-316-0662
1 Belvedere Place
Mill Valley, CA
SL Innovation Technology Group Corp.
949.291.6452
514 Avenida Victoria
San Clemente, CA


Working With Design Patterns: State

provided by: 
Originally published at Internet.com


Conditional logic is essential to building any application, yet too much can make an application incomprehensible. Many of the applications I build require that an object exist in many different states, with behavior differing from state to state. A straightforward implementation involves lots of if statements and complex conditionals, producing overly convoluted solutions in short order. As a remedy, I use the state design pattern to keep my code from getting out of hand.

Holdings in a library provide a good example. A holding is a copy of a book (see Listing 1). (In my implementation, the book is simply the ISBN classification information. Thus, each holding object references a copy number and a book object.) Holdings can be checked out, checked in, they can be moved from branch to branch, they can be held by a patron, they can be warehoused, and so on. Each of these events puts the holding into a state where different rules apply. For example, a book that's checked out obviously can't be warehoused.

Listing 1: The Book class. // BookTest.java import static org.junit.Assert.*; import org.junit.*; public class BookTest { public static final Book CATCH22 = new Book("0-671-12805-1", "Catch-22", "Heller, Joseph", "1961"); @Test public void create() { assertEquals("0-671-12805-1", CATCH22.getIsbn()); assertEquals("Catch-22", CATCH22.getTitle()); assertEquals("Heller, Joseph", CATCH22.getAuthor()); assertEquals("1961", CATCH22.getYear()); } } // Book.java public class Book { private final String isbn; private final String title; private final String author; private final String year; public Book(String isbn, String title, String author, String year) { this.isbn = isbn; this.title = title; this.author = author; this.year = year; } public String getIsbn() { return isbn; } public String getTitle() { return title; } public String getAuthor() { return author; } public String getYear() { return year; } }

Listing 2 shows a starter implementation for Holding. (Note that I'm not yet concerned with the relevancy of the patron ID.)

Listing 2: An initial Holding implementation. import static org.junit.Assert.*; import java.util.Date; import org.junit.*; public class HoldingTest { private Holding holding; private static final Date NOW = new Date(); private static final String PATRON_ID = "12345"; @Before public void initialize() { Book book = BookTest.CATCH22; int copyNumber = 1; holding = new Holding(book, copyNumber); } @Test public void create() { assertSame(BookTest.CATCH22, holding.getBook()); assertEquals(1, holding.getCopyNumber()); assertFalse(holding.isOnLoan()); } @Test public void checkout() { holding.checkout(NOW, PATRON_ID); assertTrue(holding.isOnLoan()); assertEquals(NOW, holding.getLoanDate()); } @Test public void checkin() { Date later = new Date(NOW.getTime() + 1); holding.checkout(NOW, PATRON_ID); holding.checkin(later); assertFalse(holding.isOnLoan()); } } // Holding.java import java.util.Date; public class Holding { private final Book book; private final int copyNumber; private Date checkoutDate; public Holding(Book book, int copyNumber) { this.book = book; this.copyNumber = copyNumber; } public Book getBook() { return book; } public int getCopyNumber() { return copyNumber; } public boolean isOnLoan() { return checkoutDaate != null; } public Date getLoanDate() { return checkoutDate; } public void checkout(Date date, String patronId) { checkoutDate = date; } public void checkin(Date date) { checkoutDate = null; } }

The next story I want to tackle is to allow patrons to place a hold on a book. If checked in, the librarian places a held book behind the desk. Attempts to check it out by a different patron are rejected. If checked out, the system marks the book on hold for when it's returned. Holds are only valid for three days; a daily update routine hits all holdings, giving each an opportunity to clear any expired holds. The three-day timer starts only once a book is returned, if it's checked out. A hold cannot be placed on a book already on hold.

Based on these requirements, the code to manage patron holds (see Listing 3) really isn't that bad, but I'm starting to wonder where it's headed. I must ensure I have if statements in the right place, for example, when doing an update: If I add code to check to see whether any hold needs to be cleared, but neglect to guard against the case where the holding isn't already on hold, my code throws a NullPointerException. As I consider similar features, such as transfers and placing books on reserve, I'm thinking that the code easily could start getting unwieldy and confusing.

Tracking State

A holding can be in a number of states: checked out, checked in, on hold or not, in transit between branches, and so on. For the existing code, a holding can be in one of four possible states: * checked out, on hold * checked out, not on hold * checked in, on hold * checked out, not on hold

Defining the states allows me to draw a state diagram (see Figure 1). The state diagram captures each separate state as a separate box. A holding can transition between states when specific events occur, such as the holding being checked in. Events usually trigger actions as part of transitioning to another state.



Click here for a larger image.

Figure 1: State transitions.

The state pattern says that I can take each of these states and represent them as a separate class. The current state is tracked within Holding as a reference to a state object. I define the possible events as methods on all states. Each state handles the set of events however appropriately by invoking an action on the Holding object. The event handler also is responsible for updating the state reference on the Holding object if a state transition is required.

Listing 3: Holding, revised. // HoldingTest.java import static org.junit.Assert.*; import java.util.*; import org.junit.*; public class HoldingTest { private Holding holding; private static final Date NOW = new Date(); private static final Date LATER = new Date(NOW.getTime() + 1); private static final String PATRON_ID1 = "12345"; private static final String PATRON_ID2 = "22345"; @Before public void initialize() { Book book = BookTest.CATCH22; int copyNumber = 1; holding = new Holding(book, copyNumber); } @Test public void create() { assertSame(BookTest.CATCH22, holding.getBook()); assertEquals(1, holding.getCopyNumber()); assertFalse(holding.isOnLoan()); } @Test public void checkout() { holding.checkout(NOW, PATRON_ID1); assertTrue(holding.isOnLoan()); assertEquals(NOW, holding.getLoanDate()); } @Test public void checkin() { holding.checkout(NOW, PATRON_ID1); holding.checkin(LATER); assertFalse(holding.isOnLoan()); } @Test public void placeHoldOnCheckedInHolding() { assertFalse(holding.isOnHold()); holding.placeHold(NOW, PATRON_ID1); assertTrue(holding.isOnHold()); } @Test public void rejectsDuplicateHolds() { holding.placeHold(NOW, PATRON_ID1); try { holding.placeHold(NOW, PATRON_ID2); fail(); } catch (HoldException expected) { assertTrue(holding.isOnHold()); } } @Test(expected = HoldException.class) public void holdOnCheckedOutBookRetainedOnCheckin() { holding.checkout(NOW, PATRON_ID2); holding.placeHold(NOW, PATRON_ID1); holding.checkin(LATER); assertTrue(holding.isOnHold()); holding.checkout(NOW, PATRON_ID2); } @Test public void releaseHold() { holding.placeHold(NOW, PATRON_ID1); holding.releaseAnyHold(); assertFalse(holding.isOnHold()); } @Test public void holdReleasedAfter3Days() { holding.placeHold(NOW, PATRON_ID1); holding.update(DateUtil.addDays(NOW, 1)); assertTrue(holding.isOnHold()); holding.update(DateUtil.addDays(NOW, 2)); assertTrue(holding.isOnHold()); holding.update(DateUtil.addDays(NOW, 3)); assertFalse(holding.isOnHold()); } @Test public void holdReleasedAfter3DaysAfterCheckin() { holding.checkout(NOW, PATRON_ID1); holding.placeHold(LATER, PATRON_ID1); Date checkinDate = DateUtil.addDays(NOW, 3); holding.update(checkinDate); assertTrue(holding.isOnHold()); holding.checkin(checkinDate); assertTrue(holding.isOnHold()); holding.update(DateUtil.addDays(checkinDate, 3)); assertFalse(holding.isOnHold()); } @Test public void releaseHoldHarmlessIfNoHolds() { holding.releaseAnyHold(); assertFalse(holding.isOnHold()); } @Test public void checkoutReleasesHold() { holding.placeHold(NOW, PATRON_ID1); holding.checkout(LATER, PATRON_ID1); assertFalse(holding.isOnHold()); } @Test public void rejectCheckoutForHoldByDifferentPatron() { holding.placeHold(NOW, PATRON_ID1); try { holding.checkout(NOW, PATRON_ID2); fail(); } catch (HoldException expected) { } } } // Holding.java import java.util.*; public class Holding { private final Book book; private final int copyNumber; private Date checkoutDate; private String holdPatron; private Date holdDate; public Holding(Book book, int copyNumber) { this.book = book; this.copyNumber = copyNumber; } public Book getBook() { return book; } public int getCopyNumber() { return copyNumber; } public boolean isOnLoan() { return checkoutDate != null; } public Date getLoanDate() { return checkoutDate; } public void checkout(Date date, String patronId) { if (isOnHold() && patronId != holdPatron) throw new HoldException(); releaseAnyHold(); checkoutDate = date; } public void checkin(Date date) { checkoutDate = null; } public void placeHold(Date date, String patronId) { if (isOnHold()) throw new HoldException(); this.holdPatron = patronId; holdDate = new Date(); } public boolean isOnHold() { return holdPatron != null; } public void releaseAnyHold() { holdPatron = null; } public void update(Date date) { if (isOnHold() && !isOnLoan() && DateUtil.daysBetween(holdDate, date) >= 3) releaseAnyHold(); } }

I refactor my code slowly, running tests continually. The first class I create is the HoldingState class (see Listing 4), an abstract class intended to provide null behavior for each of the possible events.

Listing 4: HoldingState. // HoldingState import java.util.*; abstract class HoldingState { protected final Holding holding; HoldingState(Holding holding) { this.holding = holding; } void checkout(Date date, String patronId) { } void checkin(Date date) { } void placeHold(Date date, String patronId) { } void update(Date date) { } }

I then create state derivatives, one for each of the three states. After I create the derivatives, I begin to move code over from the Holding class. For each event (checkout, checkin, placeHold, update), the job of the Holding object is simply to delegate the event to the current HoldingState object. For example, the checkout method in Holding ends up reading: public void checkout(Date date, String patronId) { state.checkout(date, patronId); }

Because these are simple delegations, I could consider using the Java proxy mechanism. Right now, I'm not concerned about a rapidly growing public interface on Holding, so I'll defer that enhancement.

States that need to do something with the checkout event call an action method and/or transition to another state. Other states may choose to ignore that event. One interesting result of implementing the state pattern, though, is that it may help point out a potential problem in the system by making ignored events apparent. For example, my CheckedOut state object provides no behavior for the checkout event. That unhandled event triggers me to think that I must determine what should happen if someone does try to check out a book twice.

The benefit from moving all the code into the state objects is that the conditionals begin to disappear. When in the CheckedInHeld state, I no longer have to check whether or not a book is held before I proceed: class CheckedInHeld extends HoldingState { // ... @Override public void checkout(Date date, String patronId) { if (patronId != holding.holdPatron) throw new HoldException(); holding.doCheckout(date, patronId); holding.state = new CheckedOut(holding); } // ... }

Previously, the code in checkout in Holding had to ask whether or not the book was already held. Because this code is executing when the Holding references the CheckedInHeld state, that question no longer needs to be asked.

The state classes are shown in Listing 5. Each of the state classes is small, simple, and easily could be tested directly.

Listing 5: State derivatives. // CheckedOut.java import java.util.*; class CheckedOut extends HoldingState { CheckedOut(Holding holding) { super(holding); } @Override public void checkin(Date date) { holding.doCheckin(date); holding.state = new CheckedIn(holding); } @Override public void placeHold(Date date, String patronId) { holding.doHold(date, patronId); holding.state = new CheckedOutHeld(holding); } } // CheckedIn.java import java.util.*; class CheckedIn extends HoldingState { CheckedIn(Holding holding) { super(holding); } @Override public void checkout(Date date, String patronId) { holding.doCheckout(date, patronId); holding.state = new CheckedOut(holding); } @Override public void placeHold(Date date, String patronId) { holding.doHold(date, patronId); holding.state = new CheckedInHeld(holding); } ѥ // CheckedInHeld.java import java.util.*; public class CheckedInHeld extends CheckedIn { CheckedInHeld(Holding holding) { super(holding); } @Override public void checkout(Date date, String patronId) { if (patronId != holding.holdPatron) throw new HoldException(); holding.doCheckout(date, patronId); holding.state = new CheckedOut(holding); } @Override public void placeHold(Date date, String patronId) { throw new HoldException(); } @Override public void update(Date date) { holding.doReleaseOldHold(date); } } // CheckedOutHeld.java import java.util.*; public class CheckedOutHeld extends HoldingState { CheckedOutHeld(Holding holding) { super(holding); } @Override public void checkin(Date date) { holding.doCheckin(date); holding.state = new CheckedInHeld(holding); } @Override public void placeHold(Date date, String patronId) { throw new HoldException(); } }

The Holding class that remains (see Listing 6) is now devoid of most conditional logic! I can now test it, too, with excruciating ease.

The state pattern is one of the few design patterns that requires tight coupling between its classes: The Holding class is dependent upon the initial state, and each of the states is in turn dependent upon Holding. Although there are some clever ways to break this, it's probably not necessary, because the classes represent a self-enclosed subsystem that can remain isolated from the rest of the system. For the implementation of the state classes, I took advantage of Java's package-level access, directly having the states access Holding variables as needed, but not exposing these fields to external clients of Holding. It's one of the rare cases where I won't insist that a field remain private.

Listing 6: Holding, using the state design pattern. import java.util.*; public class Holding { private final Book book; private final int copyNumber; Date checkoutDate; String holdPatron; Date holdDate; HoldingState state = new CheckedIn(this); Date checkinDate; public Holding(Book book, int copyNumber) { this.book = book; this.copyNumber = copyNumber; } public Book getBook() { return book; } public int getCopyNumber() { return copyNumber; } public boolean isOnLoan() { return checkoutDate != null; } public Date getLoanDate() { return checkoutDate; } public void checkout(Date date, String patronId) { state.checkout(date, patronId); } public void checkin(Date date) { state.checkin(date); } public void placeHold(Date date, String patronId) { state.placeHold(date, patronId); } public void update(Date date) { state.update(date); } public boolean isOnHold() { return holdPatron != null; } public void releaseAnyHold() { holdPatron = null; } // callback actions void doHold(Date date, String patronId) { holdPatron = patronId; holdDate = date; } void doCheckout(Date date, String patronId) { checkoutDate = date; releaseAnyHold(); } public void doCheckin(Date date) { checkoutDate = null; } public void doReleaseOldHold(Date updatedAt) { if (DateUtil.daysBetween(holdDate, updatedAt) >= 3) releaseAnyHold(); } }

Adding new functionality into the state diagram usually is simple and straightforward. The separate state classes help keep conditional logic to a minimum by avoiding confusion about the conditions under which something can occur. Often, modifications will necessitate changes to transitions between states, requiring updates to multiple state derivatives. Drawing a state diagram can be a good idea, but there's another possible solution to help manage the transitions.

State diagrams can be represented as simple tables. If I were to refactor to a more disciplined implementation of the state pattern, I could dramatically simplify my work. The table would define event methods and callback action method names; these would be used to automatically generate code for the state derivatives. This automation can be critical in a highly dynamic state system. The Object Mentor web site contains a download for just such a Java code generator, SMC (State Machine Compiler). There also are state pattern variants that can simplify state system changes in a more dynamic subsystem.



Cliick here for a larger image.

Figure 2: The State pattern.

About the Author

Jeff Langr is a veteran software developer with over a quarter century of professional software development experience. He's written two books, including Agile Java: Crafting Code With Test-Driven Development (Prentice Hall) in 2005. Jeff has contributed a couple chapters to Uncle Bob Martin's upcoming book, Clean Code. Jeff has written over 75 articles on software development, with over thirty appearing at Developer.com. You can find out more about Jeff at his site, http://langrsoft.com, or you can contact him via email at jeff at langrsoft dot com.

Author: Jeff Langr

Read article at Internet.com site

Featured Local Company

SpbCreative

925/7889315
1537 Boulevard Way
Walnut Creek, CA
http://www.spbcreative.com

Regional Articles
- Working With Design Patterns: State Adelanto CA
- Working With Design Patterns: State Agoura Hills CA
- Working With Design Patterns: State Alameda CA
- Working With Design Patterns: State Alhambra CA
- Working With Design Patterns: State Aliso Viejo CA
- Working With Design Patterns: State Alpine CA
- Working With Design Patterns: State Altadena CA
- Working With Design Patterns: State Anaheim CA
- Working With Design Patterns: State Antelope CA
- Working With Design Patterns: State Antioch CA
- Working With Design Patterns: State Apple Valley CA
- Working With Design Patterns: State Aptos CA
- Working With Design Patterns: State Arcadia CA
- Working With Design Patterns: State Arcata CA
- Working With Design Patterns: State Arroyo Grande CA
- Working With Design Patterns: State Arvin CA
- Working With Design Patterns: State Atascadero CA
- Working With Design Patterns: State Atwater CA
- Working With Design Patterns: State Auburn CA
- Working With Design Patterns: State Avenal CA
- Working With Design Patterns: State Azusa CA
- Working With Design Patterns: State Bakersfield CA
- Working With Design Patterns: State Baldwin Park CA
- Working With Design Patterns: State Banning CA
- Working With Design Patterns: State Barstow CA
- Working With Design Patterns: State Bell CA
- Working With Design Patterns: State Bellflower CA
- Working With Design Patterns: State Belmont CA
- Working With Design Patterns: State Benicia CA
- Working With Design Patterns: State Berkeley CA
- Working With Design Patterns: State Beverly Hills CA
- Working With Design Patterns: State Bloomington CA
- Working With Design Patterns: State Blythe CA
- Working With Design Patterns: State Bonita CA
- Working With Design Patterns: State Brawley CA
- Working With Design Patterns: State Brea CA
- Working With Design Patterns: State Brentwood CA
- Working With Design Patterns: State Buena Park CA
- Working With Design Patterns: State Burbank CA
- Working With Design Patterns: State Burlingame CA
- Working With Design Patterns: State Calabasas CA
- Working With Design Patterns: State Calexico CA
- Working With Design Patterns: State Camarillo CA
- Working With Design Patterns: State Campbell CA
- Working With Design Patterns: State Canoga Park CA
- Working With Design Patterns: State Canyon Country CA
- Working With Design Patterns: State Carlsbad CA
- Working With Design Patterns: State Carmichael CA
- Working With Design Patterns: State Carpinteria CA
- Working With Design Patterns: State Carson CA
- Working With Design Patterns: State Castaic CA
- Working With Design Patterns: State Castro Valley CA
- Working With Design Patterns: State Cathedral City CA
- Working With Design Patterns: State Ceres CA
- Working With Design Patterns: State Cerritos CA
- Working With Design Patterns: State Chatsworth CA
- Working With Design Patterns: State Chico CA
- Working With Design Patterns: State Chino CA
- Working With Design Patterns: State Chino Hills CA
- Working With Design Patterns: State Chowchilla CA
- Working With Design Patterns: State Chula Vista CA
- Working With Design Patterns: State Citrus Heights CA
- Working With Design Patterns: State Claremont CA
- Working With Design Patterns: State Clovis CA
- Working With Design Patterns: State Coachella CA
- Working With Design Patterns: State Coalinga CA
- Working With Design Patterns: State Colton CA
- Working With Design Patterns: State Compton CA
- Working With Design Patterns: State Concord CA
- Working With Design Patterns: State Corcoran CA
- Working With Design Patterns: State Corona CA
- Working With Design Patterns: State Coronado CA
- Working With Design Patterns: State Costa Mesa CA
- Working With Design Patterns: State Covina CA
- Working With Design Patterns: State Crescent City CA
- Working With Design Patterns: State Culver City CA
- Working With Design Patterns: State Cupertino CA
- Working With Design Patterns: State Cypress CA
- Working With Design Patterns: State Daly City CA
- Working With Design Patterns: State Dana Point CA
- Working With Design Patterns: State Danville CA
- Working With Design Patterns: State Davis CA
- Working With Design Patterns: State Delano CA
- Working With Design Patterns: State Desert Hot Springs CA
- Working With Design Patterns: State Diamond Bar CA
- Working With Design Patterns: State Dinuba CA
- Working With Design Patterns: State Downey CA
- Working With Design Patterns: State Duarte CA
- Working With Design Patterns: State Dublin CA
- Working With Design Patterns: State El Cajon CA
- Working With Design Patterns: State El Centro CA
- Working With Design Patterns: State El Cerrito CA
- Working With Design Patterns: State El Dorado Hills CA
- Working With Design Patterns: State El Monte CA
- Working With Design Patterns: State El Segundo CA
- Working With Design Patterns: State El Sobrante CA
- Working With Design Patterns: State Elk Grove CA
- Working With Design Patterns: State Emeryville CA
- Working With Design Patterns: State Encinitas CA
- Working With Design Patterns: State Encino CA
- Working With Design Patterns: State Escondido CA
- Working With Design Patterns: State Eureka CA
- Working With Design Patterns: State Fair Oaks CA
- Working With Design Patterns: State Fairfield CA
- Working With Design Patterns: State Fallbrook CA
- Working With Design Patterns: State Fillmore CA
- Working With Design Patterns: State Folsom CA
- Working With Design Patterns: State Fontana CA
- Working With Design Patterns: State Fountain Valley CA
- Working With Design Patterns: State Fremont CA
- Working With Design Patterns: State Fresno CA
- Working With Design Patterns: State Fullerton CA
- Working With Design Patterns: State Galt CA
- Working With Design Patterns: State Garden Grove CA
- Working With Design Patterns: State Gardena CA
- Working With Design Patterns: State Gilroy CA
- Working With Design Patterns: State Glendale CA
- Working With Design Patterns: State Glendora CA
- Working With Design Patterns: State Goleta CA
- Working With Design Patterns: State Granada Hills CA
- Working With Design Patterns: State Granite Bay CA
- Working With Design Patterns: State Grass Valley CA
- Working With Design Patterns: State Hacienda Heights CA
- Working With Design Patterns: State Half Moon Bay CA
- Working With Design Patterns: State Hanford CA
- Working With Design Patterns: State Harbor City CA
- Working With Design Patterns: State Hawaiian Gardens CA
- Working With Design Patterns: State Hawthorne CA
- Working With Design Patterns: State Hayward CA
- Working With Design Patterns: State Healdsburg CA
- Working With Design Patterns: State Hemet CA
- Working With Design Patterns: State Hercules CA
- Working With Design Patterns: State Hermosa Beach CA
- Working With Design Patterns: State Hesperia CA
- Working With Design Patterns: State Highland CA
- Working With Design Patterns: State Hollister CA
- Working With Design Patterns: State Huntington Beach CA
- Working With Design Patterns: State Huntington Park CA
- Working With Design Patterns: State Imperial Beach CA
- Working With Design Patterns: State Indio CA
- Working With Design Patterns: State Inglewood CA
- Working With Design Patterns: State Irvine CA
- Working With Design Patterns: State King City CA
- Working With Design Patterns: State La Canada Flintridge CA
- Working With Design Patterns: State La Crescenta CA
- Working With Design Patterns: State La Habra CA
- Working With Design Patterns: State La Jolla CA
- Working With Design Patterns: State La Mesa CA
- Working With Design Patterns: State La Mirada CA
- Working With Design Patterns: State La Palma CA
- Working With Design Patterns: State La Puente CA
- Working With Design Patterns: State La Quinta CA
- Working With Design Patterns: State La Verne CA
- Working With Design Patterns: State Laguna Beach CA
- Working With Design Patterns: State Laguna Hills CA
- Working With Design Patterns: State Laguna Niguel CA
- Working With Design Patterns: State Lake Elsinore CA
- Working With Design Patterns: State Lake Forest CA
- Working With Design Patterns: State Lakeside CA
- Working With Design Patterns: State Lakewood CA
- Working With Design Patterns: State Lamont CA
- Working With Design Patterns: State Lancaster CA
- Working With Design Patterns: State Lawndale CA
- Working With Design Patterns: State Lemon Grove CA
- Working With Design Patterns: State Lemoore CA
- Working With Design Patterns: State Livermore CA
- Working With Design Patterns: State Lodi CA
- Working With Design Patterns: State Loma Linda CA
- Working With Design Patterns: State Lomita CA
- Working With Design Patterns: State Lompoc CA
- Working With Design Patterns: State Long Beach CA
- Working With Design Patterns: State Los Alamitos CA
- Working With Design Patterns: State Los Altos CA
- Working With Design Patterns: State Los Angeles CA
- Working With Design Patterns: State Los Banos CA
- Working With Design Patterns: State Los Gatos CA
- Working With Design Patterns: State Los Osos CA
- Working With Design Patterns: State Lynwood CA
- Working With Design Patterns: State Madera CA
- Working With Design Patterns: State Malibu CA
- Working With Design Patterns: State Manhattan Beach CA
- Working With Design Patterns: State Manteca CA
- Working With Design Patterns: State Marina CA
- Working With Design Patterns: State Marina Del Rey CA
- Working With Design Patterns: State Martinez CA
- Working With Design Patterns: State Marysville CA
- Working With Design Patterns: State Maywood CA
- Working With Design Patterns: State Mckinleyville CA
- Working With Design Patterns: State Menlo Park CA
- Working With Design Patterns: State Merced CA
- Working With Design Patterns: State Mill Valley CA
- Working With Design Patterns: State Millbrae CA
- Working With Design Patterns: State Milpitas CA
- Working With Design Patterns: State Mira Loma CA
- Working With Design Patterns: State Mission Hills CA
- Working With Design Patterns: State Mission Viejo CA
- Working With Design Patterns: State Modesto CA
- Working With Design Patterns: State Monrovia CA
- Working With Design Patterns: State Montclair CA
- Working With Design Patterns: State Montebello CA
- Working With Design Patterns: State Monterey CA
- Working With Design Patterns: State Monterey Park CA
- Working With Design Patterns: State Moorpark CA
- Working With Design Patterns: State Moraga CA
- Working With Design Patterns: State Moreno Valley CA
- Working With Design Patterns: State Morgan Hill CA
- Working With Design Patterns: State Mountain View CA
- Working With Design Patterns: State Murrieta CA
- Working With Design Patterns: State Napa CA
- Working With Design Patterns: State National City CA
- Working With Design Patterns: State Nevada City CA
- Working With Design Patterns: State Newark CA
- Working With Design Patterns: State Newbury Park CA
- Working With Design Patterns: State Newhall CA
- Working With Design Patterns: State Newport Beach CA
- Working With Design Patterns: State Nipomo CA
- Working With Design Patterns: State Norco CA
- Working With Design Patterns: State North Highlands CA
- Working With Design Patterns: State North Hills CA
- Working With Design Patterns: State North Hollywood CA
- Working With Design Patterns: State Northridge CA
- Working With Design Patterns: State Norwalk CA
- Working With Design Patterns: State Novato CA
- Working With Design Patterns: State Oakdale CA
- Working With Design Patterns: State Oakland CA
- Working With Design Patterns: State Oakley CA
- Working With Design Patterns: State Oceanside CA
- Working With Design Patterns: State Ojai CA
- Working With Design Patterns: State Ontario CA
- Working With Design Patterns: State Orange CA
- Working With Design Patterns: State Orangevale CA
- Working With Design Patterns: State Orinda CA
- Working With Design Patterns: State Oroville CA
- Working With Design Patterns: State Oxnard CA
- Working With Design Patterns: State Pacific Grove CA
- Working With Design Patterns: State Pacific Palisades CA
- Working With Design Patterns: State Pacifica CA
- Working With Design Patterns: State Pacoima CA
- Working With Design Patterns: State Palm Desert CA
- Working With Design Patterns: State Palm Springs CA
- Working With Design Patterns: State Palmdale CA
- Working With Design Patterns: State Palo Alto CA
- Working With Design Patterns: State Palos Verdes Peninsula CA
- Working With Design Patterns: State Panorama City CA
- Working With Design Patterns: State Paradise CA
- Working With Design Patterns: State Paramount CA
- Working With Design Patterns: State Pasadena CA
- Working With Design Patterns: State Paso Robles CA
- Working With Design Patterns: State Patterson CA
- Working With Design Patterns: State Perris CA
- Working With Design Patterns: State Petaluma CA
- Working With Design Patterns: State Pico Rivera CA
- Working With Design Patterns: State Pinole CA
- Working With Design Patterns: State Pittsburg CA
- Working With Design Patterns: State Placentia CA
- Working With Design Patterns: State Placerville CA
- Working With Design Patterns: State Pleasant Hill CA
- Working With Design Patterns: State Pleasanton CA
- Working With Design Patterns: State Pomona CA
- Working With Design Patterns: State Port Hueneme CA
- Working With Design Patterns: State Porterville CA
- Working With Design Patterns: State Poway CA
- Working With Design Patterns: State Ramona CA
- Working With Design Patterns: State Rancho Cordova CA
- Working With Design Patterns: State Rancho Cucamonga CA
- Working With Design Patterns: State Rancho Palos Verdes CA
- Working With Design Patterns: State Rancho Santa Margarita CA
- Working With Design Patterns: State Red Bluff CA
- Working With Design Patterns: State Redding CA
- Working With Design Patterns: State Redlands CA
- Working With Design Patterns: State Redondo Beach CA
- Working With Design Patterns: State Redwood City CA
- Working With Design Patterns: State Reedley CA
- Working With Design Patterns: State Reseda CA
- Working With Design Patterns: State Rialto CA
- Working With Design Patterns: State Richmond CA
- Working With Design Patterns: State Ridgecrest CA
- Working With Design Patterns: State Riverbank CA
- Working With Design Patterns: State Riverside CA
- Working With Design Patterns: State Rocklin CA
- Working With Design Patterns: State Rohnert Park CA
- Working With Design Patterns: State Rosamond CA
- Working With Design Patterns: State Rosemead CA
- Working With Design Patterns: State Roseville CA
- Working With Design Patterns: State Rowland Heights CA
- Working With Design Patterns: State Sacramento CA
- Working With Design Patterns: State Salinas CA
- Working With Design Patterns: State San Anselmo CA
- Working With Design Patterns: State San Bernardino CA
- Working With Design Patterns: State San Bruno CA
- Working With Design Patterns: State San Carlos CA
- Working With Design Patterns: State San Clemente CA
- Working With Design Patterns: State San Diego CA
- Working With Design Patterns: State San Dimas CA
- Working With Design Patterns: State San Fernando CA
- Working With Design Patterns: State San Francisco CA
- Working With Design Patterns: State San Gabriel CA
- Working With Design Patterns: State San Jacinto CA
- Working With Design Patterns: State San Jose CA
- Working With Design Patterns: State San Juan Capistrano CA
- Working With Design Patterns: State San Leandro CA
- Working With Design Patterns: State San Lorenzo CA
- Working With Design Patterns: State San Luis Obispo CA
- Working With Design Patterns: State San Marcos CA
- Working With Design Patterns: State San Mateo CA
- Working With Design Patterns: State San Pablo CA
- Working With Design Patterns: State San Pedro CA
- Working With Design Patterns: State San Rafael CA
- Working With Design Patterns: State San Ramon CA
- Working With Design Patterns: State San Ysidro CA
- Working With Design Patterns: State Sanger CA
- Working With Design Patterns: State Santa Ana CA
- Working With Design Patterns: State Santa Barbara CA
- Working With Design Patterns: State Santa Clara CA
- Working With Design Patterns: State Santa Clarita CA
- Working With Design Patterns: State Santa Cruz CA
- Working With Design Patterns: State Santa Fe Springs CA
- Working With Design Patterns: State Santa Maria CA
- Working With Design Patterns: State Santa Monica CA
- Working With Design Patterns: State Santa Paula CA
- Working With Design Patterns: State Santa Rosa CA
- Working With Design Patterns: State Santee CA
- Working With Design Patterns: State Saratoga CA
- Working With Design Patterns: State Scotts Valley CA
- Working With Design Patterns: State Seal Beach CA
- Working With Design Patterns: State Seaside CA
- Working With Design Patterns: State Sebastopol CA
- Working With Design Patterns: State Selma CA
- Working With Design Patterns: State Shafter CA
- Working With Design Patterns: State Sherman Oaks CA
- Working With Design Patterns: State Shingle Springs CA
- Working With Design Patterns: State Simi Valley CA
- Working With Design Patterns: State Sonoma CA
- Working With Design Patterns: State Sonora CA
- Working With Design Patterns: State South El Monte CA
- Working With Design Patterns: State South Gate CA
- Working With Design Patterns: State South Lake Tahoe CA
- Working With Design Patterns: State South Pasadena CA
-