Skip to content

Refactor Prototype pattern (Closes #584) #1970

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lombok.config
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
lombok.log.fieldName = LOGGER

lombok.addLombokGeneratedAnnotation = true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exclude Lombok auto-generated code from code-coverage

23 changes: 10 additions & 13 deletions prototype/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ used for creating new objects from prototype instances.

Real-world example

> Remember Dolly? The sheep that was cloned! Lets not get into the details but the key point here is
> Remember Dolly? The sheep that was cloned! Let's not get into the details but the key point here is
> that it is all about cloning.

In plain words
Expand All @@ -45,24 +45,25 @@ interface with a method for cloning objects. In this example, `Prototype` interf
this with its `copy` method.

```java
public interface Prototype {
Object copy();
public abstract class Prototype<T> implements Cloneable {
@SneakyThrows
public T copy() {
return (T) super.clone();
}
}
```

Our example contains a hierarchy of different creatures. For example, let's look at `Beast` and
`OrcBeast` classes.

```java
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public abstract class Beast implements Prototype {
public abstract class Beast extends Prototype<Beast> {

public Beast(Beast source) {
}

@Override
public abstract Beast copy();
}

@EqualsAndHashCode(callSuper = false)
Expand All @@ -76,19 +77,15 @@ public class OrcBeast extends Beast {
this.weapon = orcBeast.weapon;
}

@Override
public OrcBeast copy() {
return new OrcBeast(this);
}

@Override
public String toString() {
return "Orcish wolf attacks with " + weapon;
}

}
```

We don't want to go into too much details, but the full example contains also base classes `Mage`
We don't want to go into too many details, but the full example contains also base classes `Mage`
and `Warlord` and there are specialized implementations for those for elves in addition to orcs.

To take full advantage of the prototype pattern, we create `HeroFactory` and `HeroFactoryImpl`
Expand Down
7 changes: 2 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/Beast.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@
/**
* Beast.
*/
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public abstract class Beast implements Prototype {
public abstract class Beast extends Prototype<Beast> {

public Beast(Beast source) {
}

@Override
public abstract Beast copy();

}
5 changes: 0 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/ElfBeast.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public ElfBeast(ElfBeast elfBeast) {
this.helpType = elfBeast.helpType;
}

@Override
public ElfBeast copy() {
return new ElfBeast(this);
}

@Override
public String toString() {
return "Elven eagle helps in " + helpType;
Expand Down
5 changes: 0 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/ElfMage.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public ElfMage(ElfMage elfMage) {
this.helpType = elfMage.helpType;
}

@Override
public ElfMage copy() {
return new ElfMage(this);
}

@Override
public String toString() {
return "Elven mage helps in " + helpType;
Expand Down
15 changes: 4 additions & 11 deletions prototype/src/main/java/com/iluwatar/prototype/ElfWarlord.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,31 +24,24 @@
package com.iluwatar.prototype;

import lombok.EqualsAndHashCode;
import lombok.RequiredArgsConstructor;

/**
* ElfWarlord.
*/
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = true)
@RequiredArgsConstructor
public class ElfWarlord extends Warlord {

private final String helpType;

public ElfWarlord(String helpType) {
this.helpType = helpType;
}

public ElfWarlord(ElfWarlord elfWarlord) {
super(elfWarlord);
this.helpType = elfWarlord.helpType;
}

@Override
public ElfWarlord copy() {
return new ElfWarlord(this);
}

@Override
public String toString() {
return "Elven warlord helps in " + helpType;
}
}
}
7 changes: 2 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/Mage.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@
/**
* Mage.
*/
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public abstract class Mage implements Prototype {
public abstract class Mage extends Prototype<Mage> {

public Mage(Mage source) {
}

@Override
public abstract Mage copy();

}
5 changes: 0 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/OrcBeast.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public OrcBeast(OrcBeast orcBeast) {
this.weapon = orcBeast.weapon;
}

@Override
public OrcBeast copy() {
return new OrcBeast(this);
}

@Override
public String toString() {
return "Orcish wolf attacks with " + weapon;
Expand Down
5 changes: 0 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/OrcMage.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public OrcMage(OrcMage orcMage) {
this.weapon = orcMage.weapon;
}

@Override
public OrcMage copy() {
return new OrcMage(this);
}

@Override
public String toString() {
return "Orcish mage attacks with " + weapon;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,6 @@ public OrcWarlord(OrcWarlord orcWarlord) {
this.weapon = orcWarlord.weapon;
}

@Override
public OrcWarlord copy() {
return new OrcWarlord(this);
}

@Override
public String toString() {
return "Orcish warlord attacks with " + weapon;
Expand Down
16 changes: 13 additions & 3 deletions prototype/src/main/java/com/iluwatar/prototype/Prototype.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,21 @@

package com.iluwatar.prototype;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
* Prototype.
*/
public interface Prototype {

Object copy();
@Slf4j
public abstract class Prototype<T> implements Cloneable {

/**
* Object a shallow copy of this object or null if this object is not Cloneable.
*/
@SuppressWarnings("unchecked")
@SneakyThrows
public T copy() {
return (T) super.clone();
}
}
7 changes: 2 additions & 5 deletions prototype/src/main/java/com/iluwatar/prototype/Warlord.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,11 @@
/**
* Warlord.
*/
@EqualsAndHashCode
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public abstract class Warlord implements Prototype {
public abstract class Warlord extends Prototype<Warlord> {

public Warlord(Warlord source) {
}

@Override
public abstract Warlord copy();

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
* @param <P> Prototype
* @author Jeroen Meulemeester
*/
class PrototypeTest<P extends Prototype> {
class PrototypeTest<P extends Prototype<P>> {
static Collection<Object[]> dataProvider() {
return List.of(
new Object[]{new OrcBeast("axe"), "Orcish wolf attacks with axe"},
Expand Down