Skip to content

Instantly share code, notes, and snippets.

@pdurbin
Last active April 10, 2018 16:03
Show Gist options
  • Save pdurbin/f2a34896377b6777acc6 to your computer and use it in GitHub Desktop.
Save pdurbin/f2a34896377b6777acc6 to your computer and use it in GitHub Desktop.
Java interfaces vs. abstract classes
*.class
target

Java interfaces vs. abstract classes

Early on in Head First Design Patterns the authors say, "'Program to an interface' really means 'Program to a supertype'".

By replacing public interface FlyBehavior with public abstract class FlyBehavior from the book's strategy pattern example at http://www.headfirstlabs.com/books/hfdp/HeadFirstDesignPatterns_code102507.zip we can try this out:

diagram of abstract classes

$ javac *.java
$ java Run
I'm a real Mallard duck
I'm flying!!
I'm a rubber duckie
I can't fly
$ ./plantuml.sh
Creating abstract-classes.uml...
PlantUMLDoclet.createPlantUml() -  start
open outputfile: abstract-classes.uml
write interfaces/ abstract classes...
write content...
write Element MallardDuck...
write Element Duck...
write Element FlyWithWings...
write Element FlyNoWay...
write Element RubberDuck...
write Element FlyBehavior...
PlantUMLDoclet.createPlantUml() -  end
Done.
Converting abstract-classes.uml to png...
Done.

If you have Maven installed:

  • mvn clean compile package exec:java --quiet
  • java -jar target/supertype*jar

See also:

@startuml
' definitions
' -----------
' package ""
abstract Duck
abstract FlyBehavior
class FlyNoWay
class FlyWithWings
class MallardDuck
class RubberDuck
' end package
' content
' -------
' Duck:
Duck --> "1" FlyBehavior
Duck : void setFlyBehavior(FlyBehavior)
Duck : void performFly()
Duck : void swim()
' MallardDuck:
Duck <|-- MallardDuck
MallardDuck : void display()
' RubberDuck:
Duck <|-- RubberDuck
RubberDuck : void display()
' FlyWithWings:
FlyBehavior <|-- FlyWithWings
' FlyNoWay:
FlyBehavior <|-- FlyNoWay
' FlyBehavior:
@enduml
public abstract class Duck {
FlyBehavior flyBehavior;
public Duck() {
}
public void setFlyBehavior(FlyBehavior fb) {
flyBehavior = fb;
}
abstract void display();
public void performFly() {
flyBehavior.fly();
}
public void swim() {
System.out.println("All ducks float, even decoys!");
}
}
//public interface FlyBehavior {
// public void fly();
//}
public abstract class FlyBehavior {
/**
* Interfaces only allow public methods but by using an abstract class, we
* can declare a protected method.
*/
abstract protected void fly();
}
//public class FlyNoWay implements FlyBehavior {
public class FlyNoWay extends FlyBehavior {
@Override
//public void fly() {
protected void fly() {
System.out.println("I can't fly");
}
}
//public class FlyWithWings implements FlyBehavior {
public class FlyWithWings extends FlyBehavior {
@Override
//public void fly() {
protected void fly() {
System.out.println("I'm flying!!");
}
}
@startuml
' definitions
' -----------
' package ""
abstract Duck
interface FlyBehavior
class FlyNoWay
class FlyWithWings
class MallardDuck
class RubberDuck
' end package
' content
' -------
' MallardDuck:
Duck <|-- MallardDuck
MallardDuck : void display()
' FlyWithWings:
FlyBehavior <|.. FlyWithWings
FlyWithWings : void fly()
' FlyBehavior:
FlyBehavior : void fly()
' RubberDuck:
Duck <|-- RubberDuck
RubberDuck : void display()
' FlyNoWay:
FlyBehavior <|.. FlyNoWay
FlyNoWay : void fly()
' Duck:
Duck --> "1" FlyBehavior
Duck : void setFlyBehavior(FlyBehavior)
Duck : void performFly()
Duck : void swim()
@enduml
public class MallardDuck extends Duck {
public MallardDuck() {
flyBehavior = new FlyWithWings();
}
@Override
public void display() {
System.out.println("I'm a real Mallard duck");
}
}
#!/bin/sh
UML='abstract-classes.uml'
echo "Creating $UML..."
javadoc \
-private \
-quiet \
-J-DdestinationFile=$UML \
-J-DcreatePackages=false \
-J-DshowPublicMethods=true \
-J-DshowPublicConstructors=false \
-J-DshowPublicFields=true \
-doclet de.mallox.doclet.PlantUMLDoclet -docletpath ~/bin/plantUmlDoclet.jar \
-sourcepath . Duck.java FlyBehavior.java FlyNoWay.java FlyWithWings.java MallardDuck.java RubberDuck.java
echo "Done."
TYPE='png'
echo "Converting $UML to $TYPE..."
java -jar ~/bin/plantuml.jar -graphvizdot ~/bin/dot -t $TYPE $UML
echo "Done."
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>.</groupId>
<artifactId>supertype</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>supertype</name>
<url>http://maven.apache.org</url>
<build>
<sourceDirectory>.</sourceDirectory>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>Run</mainClass>
<arguments>
<argument>argument1</argument>
</arguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>Run</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
public class RubberDuck extends Duck {
public RubberDuck() {
flyBehavior = new FlyNoWay();
}
@Override
public void display() {
System.out.println("I'm a rubber duckie");
}
}
public class Run {
public static void main(String[] args) {
MallardDuck mallard = new MallardDuck();
RubberDuck rubberDuckie = new RubberDuck();
mallard.display();
mallard.performFly();
rubberDuckie.display();
rubberDuckie.performFly();
}
}
@jmbruel
Copy link

jmbruel commented Nov 23, 2014

Thanks for sharing. Great job (plantuml diagram generation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment