Head First Design Patterns: A Brain-Friendly Guide

Author: Eric Freeman, Elisabeth Freeman, Kathy Sierra, Bert Bates
4.5
All Stack Overflow 99
This Year Stack Overflow 9
This Month Stack Overflow 1

Comments

by anonymous   2017-08-20

You have to make up your mind whether the so called apple-specific method (in this case checkPrice()) is really specific to Apple. Or it is actually generally applicable to all fruits.

A method that is generally applicable should be declared in the base class

Assuming the answer is yes (in this case it does seems to be yes), then you should declare the method in the base class. In this case you can iterate through all the different types of fruits, and all of them would accept the method checkPrice(), so you don't even need to make a special case for apples.

A method that isn't generally applicable can be declared in an interface

What if the answer is no? Let's assume we need another method called getJuicePrice(), and we further assume that only some fruits can be made into juice (apple juice, orange juice) but other cannot (pineapple? durian?). In this case, a simple solution is to declare an interface, and only the fruits for which the method is appropriate would implement the interface. So let's say this interface is JuiceBehavior

package fruitcart;

import java.math.BigDecimal;

public interface JuiceBehavior {
    BigDecimal getJuicePrice();
}

And all fruits for which juice behavior is applicable (yes for Apple, no for Durian) would implement the interface:

package fruitcart;

import java.math.BigDecimal;

public class Apple implements JuiceBehavior {

    @Override
    public BigDecimal getJuicePrice() {
        // FIXME implement this
        return null;
    }

}

And then in your loop, what you check is whether a fruit is instanceof the interface:

if (fruit instanceof JuiceBehavior) {
    System.out.format("can be made into juice "
        + "with price $ %.2f%n", fruit.getJuicePrice());
} else {
    System.out.format("cannot be made into juice %n");

}

This solution would work for simple cases, but in more complicated cases, you may notice that you start to duplicate a lot of implementation code for getJuicePrice() for different types of fruits. This leads to the next topic

Design Pattern: Strategy

You may want to start thinking about the Design Pattern called Strategy, which further encapsulates JuiceBehavior and make it into a family of classes representing different juice behaviors. It also let you set different types of fruits to take different implementations of JuiceBehavior. I won't go into the details here. But you can read up on that on some books about Design Patterns. Such as

  1. Design Patterns: Elements of Reusable Object-Oriented Software
  2. Head First Design Patterns: A Brain-Friendly Guide
by anonymous   2017-08-20

The Decorator Pattern is probably the most straight forward one to use and would be a good one to extend concrete objects functionality and/or characteristics.

Here is some light reading: Head First Design Patterns - CH3 pdf

FYI, couple must have's for learning and referencing design patterns regardless your language of choice:

1) Head First Design Patterns

2) Patterns for Enterprise Application Architecture

3) Design Patterns: Elements of Reusable Object-Oriented Software

And sites:

1) DoFactory

2) StackOverflow Design Patterns Newbie

There are a few others, I'll have to dig them up.

by anonymous   2017-08-20

To study design patterns I would recommend going first with the book Head First Design Patterns and try to build simple examples yourself. Once you do that you will start recognizing patters everywhere you look :). Once you know what they look like you can pick up any popular open source project and you will find ton of examples there.

Actually you don't even have to look much as there are many examples of design patterns in jdk you are using already: Examples of GoF Design Patterns in Java's core libraries

by anonymous   2017-08-20

Should I using other patterns?

No, you should not insist on a single pattern.

No design pattern books will ever advise you to use a single pattern. Just like you cannot chop all ingredients in one single way (are you going to dice the spaghetti?), you cannot organise all logic in one single pattern.

Sure, you can make all your Objects use the initialiser pattern, and don't use constructors at all. This is ok. Been there, done that. I like it.

But these objects can be used with Builder or Abstract Factory (if it make things simpler). As long as the builders/factories themselves have initialiser, and that they properly initialise the created objects, then your use of the initialiser pattern will be consistent. Outside of creational patterns, it is usually good to organise objects with structural and behavioural patterns. They do not conflict with initialiser at all.

For example, look at DOM. All nodes are created by the Document object - elements, text nodes, comments, even events. This is the Factory pattern.

Yet the Document object is also a Facade! From it you access the whole system's status, objects, data, you can even write to it! Every DOM operation starts from the Document, it is the Facade of the DOM system.

DOM nodes also implements multiple patterns. They are organised in Composite, let you listen to events with Observer and Command, and handle events in a Chain of Responsibility. They are certainly parsed by an Interpreter, DocumentFragment is a Proxy, svg elements are implemented as Decorators, and createNodeIterator obviously gives you an Iterator.

The point is, good object-oriented design will yield multiple design patterns as a result, intentional or not.


What are the secrets for good code appearance

I think the best looking code is the one that is easiest to understand to you, and the way you read code changes as you gain more experience.

For example my style is too condensed for most programmers, but to me it strikes a good balance. So do develop your own style - you are not me, and you are not yesterday's you either.

Remember this as we go through the styles.

At the lowest level we have coding style - most importantly indent and bracket.

This one is simple, pick the one you like and stick with it. There are language specific styles, and they are often good starting points. Configure your IDE's formatter so that you can format all your code with hotkey.

Above the code syntax we have comment style and naming convention.

Setting rules on comment is fine, sometimes it is necessary for documenting tools. Avoid too much comment in practice. You may also want to decide your namespace and your stand on naming function expressions.

Above these structures, we have logic conventions.

The same code logic can often be done in many ways, some more 'beautiful' than the others in your eyes. Look at this example.

I picked the second style on first sight: no duplicate, logic is sectioned cleanly, format is not my style but reasonable. But many programmers would prefer the first style: logic is plain as day, a few duplications is worth it. While abstract, this level is quite deep - present your logic the wrong way actually increase the chance an experienced programmer read it wrong.

Finally, we arrives at the level of design pattern, about as far as code beauty goes.

The key to keep your code structure beautiful, is using the right patterns at right level to consistently accomplish loose coupling and code reuse, while avoiding pitfalls and over-design.

There are quite some books about beautiful code, and then there are even more books about designing and implementing beautiful software. (Decide for yourself which are beyond your level.) Knowledge is as important as experience, and you can gain them only by spending your time to study, to write, and to revise/refactor your apps.

Feel free to change your mind as you explore and experiment with your code. Changing your mind is a good sign of learning.

But first, familiarise yourself with design patterns. Just don't forget, they are the generic result of applying object-oriented principals to common tasks. It is still up to you to do the design.

Design Patterns Are Not Silver Bullets.

by anonymous   2017-08-20

There are some great OOP books from Head First covering Object-Oriented Analysis and Design and Object-Oriented Design Patterns.

by anonymous   2017-08-20

It sounds like you're asking about a general philosophy of Object-Oriented Programming. In general, you'll find that modelling real-world objects to classes doesn't always make the best sense for your code.

One guideline that's helped me figure this stuff out is a dialogue between two anthropomorphic classes (if someone knows the original source of this quote, I'd appreciate a link!):

Class A says to Class B: "Give me the value of x."

Class B: "Why do you want the value of x?"

Class A: "So I can flange it."

Class B: "Ask me, and I'll flange it for you."

This helps drive home the point that a class is meant to encapsulate the data and perform manipulations on it. In general, this is a parable that's helped me organize my code better.

Another thing you may want to look at are some common Object-Oriented Design Patterns. Something like game dice might make more sense as a Singleton, since you don't need more than one instance of it.

If you'd like a good introduction to Design Patterns, I'd recommend picking up the excellent Head First Design Patterns book.

by anonymous   2017-08-20

This gives a good list of all the patterns. (scroll about halfway down)

http://en.wikipedia.org/wiki/Software_design_pattern

Also, if you want to read about design patters, I highly suggest Head First Design Patters. You can learn all about them, and how they function, and when to use them. I used this book in my web development classes and loved it.

http://www.amazon.com/First-Design-Patterns-Elisabeth-Freeman/dp/0596007124

Hope that answered your question!

by donnfelker   2017-08-19

What books can help you expand your knowledge of design patterns?

The second one (GoF book) is the defacto standard, but unfortunately, it's also a cure for insomnia. The first one is much more entertaining.

by CastigatRidendoMores   2017-08-19

When you start building a large piece of software, it's easy to get to the point where you think "Well this is starting to suck. I wish I had started building it like this instead." Those hard-earned lessons are design patterns. If you use the right one, the code you have in the later parts of the project will be easy to scale, easy to adapt to new requirements, and generally painless compared to how it would be without careful planning. Design patterns exist because the same problems tend to pop up repeatedly, so it's worth learning about them (before you need them).

It's difficult to give a general example because design patterns typically serve to solve involved technical problems you don't encounter until deep in a project. However, if you're looking for a good place to start I recommend checking out the Decorator Pattern . There are other good sources explaining them, but a lot of them tend to hurt your brain.

by dev_bry   2017-08-19

>I'm sort of unsure how to manage sufficiently complex programs without dreaming up some complicated arrangement of classes.

Looks like you haven't gone beyond <100 KLoC code bases so I'm going to go against the grain here and suggest you dig deeper into OO:

  • learn Design Patterns, when to use them and when NOT to use them. The seminal books here are GoF and PoEAA , but you may want to consider other books like HFDP .
  • go to Github and skim through the code of your favorite open source software and see how they structure their code.
  • on second thought, your "complicated arrangement of classes" may be a sign that you're doing OO for the sake of OO and not for improving maintainability of your code. You should brush up on basic OO principles via books like Code Complete 2 , Clean Code , and Refactoring .

Learning FP is great and all, but if overcomplicating things and not being able to see the big picture when building a system are your current problems, you're still going to encounter them even if you switch to FP.