issue 508 - using copy constructor to implement prototype.
As per http://www.artima.com/intv/bloch13.html, clone method in java is broken or confusing. So staying away from clone method.
This commit is contained in:
		@@ -52,7 +52,7 @@ public class App {
 | 
			
		||||
    Warlord warlord;
 | 
			
		||||
    Beast beast;
 | 
			
		||||
 | 
			
		||||
    factory = new HeroFactoryImpl(new ElfMage(), new ElfWarlord(), new ElfBeast());
 | 
			
		||||
    factory = new HeroFactoryImpl(new ElfMage("cooking"), new ElfWarlord("cleaning"), new ElfBeast("protecting"));
 | 
			
		||||
    mage = factory.createMage();
 | 
			
		||||
    warlord = factory.createWarlord();
 | 
			
		||||
    beast = factory.createBeast();
 | 
			
		||||
@@ -60,7 +60,7 @@ public class App {
 | 
			
		||||
    LOGGER.info(warlord.toString());
 | 
			
		||||
    LOGGER.info(beast.toString());
 | 
			
		||||
 | 
			
		||||
    factory = new HeroFactoryImpl(new OrcMage(), new OrcWarlord(), new OrcBeast());
 | 
			
		||||
    factory = new HeroFactoryImpl(new OrcMage("axe"), new OrcWarlord("sword"), new OrcBeast("laser"));
 | 
			
		||||
    mage = factory.createMage();
 | 
			
		||||
    warlord = factory.createWarlord();
 | 
			
		||||
    beast = factory.createBeast();
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,6 @@ package com.iluwatar.prototype;
 | 
			
		||||
public abstract class Beast extends Prototype {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public abstract Beast clone() throws CloneNotSupportedException;
 | 
			
		||||
  public abstract Beast copy() throws CloneNotSupportedException;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,17 +28,25 @@ package com.iluwatar.prototype;
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class ElfBeast extends Beast {
 | 
			
		||||
  
 | 
			
		||||
  private String helpType;
 | 
			
		||||
 | 
			
		||||
  public ElfBeast() {}
 | 
			
		||||
  public ElfBeast(String helpType) {
 | 
			
		||||
    this.helpType = helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public ElfBeast(ElfBeast elfBeast) {
 | 
			
		||||
    this.helpType = elfBeast.helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Beast clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfBeast();
 | 
			
		||||
  public Beast copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfBeast(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Elven eagle";
 | 
			
		||||
    return "Elven eagle helps in " + helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,25 @@ package com.iluwatar.prototype;
 | 
			
		||||
 */
 | 
			
		||||
public class ElfMage extends Mage {
 | 
			
		||||
 | 
			
		||||
  public ElfMage() {}
 | 
			
		||||
  
 | 
			
		||||
  private String helpType;
 | 
			
		||||
  
 | 
			
		||||
  public ElfMage(String helpType) {
 | 
			
		||||
    this.helpType = helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public ElfMage(ElfMage elfMage) {
 | 
			
		||||
    this.helpType = elfMage.helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Mage clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfMage();
 | 
			
		||||
  public ElfMage copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfMage(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Elven mage";
 | 
			
		||||
    return "Elven mage helps in " + helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,24 @@ package com.iluwatar.prototype;
 | 
			
		||||
 */
 | 
			
		||||
public class ElfWarlord extends Warlord {
 | 
			
		||||
 | 
			
		||||
  public ElfWarlord() {}
 | 
			
		||||
  private String helpType;
 | 
			
		||||
  
 | 
			
		||||
  public ElfWarlord(String helpType) {
 | 
			
		||||
    this.helpType = helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public ElfWarlord(ElfWarlord elfWarlord) {
 | 
			
		||||
    this.helpType = elfWarlord.helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Warlord clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfWarlord();
 | 
			
		||||
  public ElfWarlord copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new ElfWarlord(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Elven warlord";
 | 
			
		||||
    return "Elven warlord helps in " + helpType;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ public class HeroFactoryImpl implements HeroFactory {
 | 
			
		||||
   */
 | 
			
		||||
  public Mage createMage() {
 | 
			
		||||
    try {
 | 
			
		||||
      return mage.clone();
 | 
			
		||||
      return mage.copy();
 | 
			
		||||
    } catch (CloneNotSupportedException e) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -58,7 +58,7 @@ public class HeroFactoryImpl implements HeroFactory {
 | 
			
		||||
   */
 | 
			
		||||
  public Warlord createWarlord() {
 | 
			
		||||
    try {
 | 
			
		||||
      return warlord.clone();
 | 
			
		||||
      return warlord.copy();
 | 
			
		||||
    } catch (CloneNotSupportedException e) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
@@ -69,7 +69,7 @@ public class HeroFactoryImpl implements HeroFactory {
 | 
			
		||||
   */
 | 
			
		||||
  public Beast createBeast() {
 | 
			
		||||
    try {
 | 
			
		||||
      return beast.clone();
 | 
			
		||||
      return beast.copy();
 | 
			
		||||
    } catch (CloneNotSupportedException e) {
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,6 @@ package com.iluwatar.prototype;
 | 
			
		||||
public abstract class Mage extends Prototype {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public abstract Mage clone() throws CloneNotSupportedException;
 | 
			
		||||
  public abstract Mage copy() throws CloneNotSupportedException;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -28,17 +28,26 @@ package com.iluwatar.prototype;
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class OrcBeast extends Beast {
 | 
			
		||||
  
 | 
			
		||||
  private String weapon;
 | 
			
		||||
 | 
			
		||||
  public OrcBeast() {}
 | 
			
		||||
  public OrcBeast(String weapon) {
 | 
			
		||||
    this.weapon = weapon;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  public OrcBeast(OrcBeast orcBeast) {
 | 
			
		||||
    this.weapon = orcBeast.weapon;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Beast clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcBeast();
 | 
			
		||||
  public Beast copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcBeast(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Orcish wolf";
 | 
			
		||||
    return "Orcish wolf attacks with " + weapon;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,24 @@ package com.iluwatar.prototype;
 | 
			
		||||
 */
 | 
			
		||||
public class OrcMage extends Mage {
 | 
			
		||||
 | 
			
		||||
  public OrcMage() {}
 | 
			
		||||
  private String weapon;
 | 
			
		||||
 | 
			
		||||
  public OrcMage(String weapon) {
 | 
			
		||||
    this.weapon = weapon;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  public OrcMage(OrcMage orcMage) {
 | 
			
		||||
    this.weapon = orcMage.weapon;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Mage clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcMage();
 | 
			
		||||
  public OrcMage copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcMage(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Orcish mage";
 | 
			
		||||
    return "Orcish mage attacks with " + weapon;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,24 @@ package com.iluwatar.prototype;
 | 
			
		||||
 */
 | 
			
		||||
public class OrcWarlord extends Warlord {
 | 
			
		||||
 | 
			
		||||
  public OrcWarlord() {}
 | 
			
		||||
  private String weapon;
 | 
			
		||||
 | 
			
		||||
  public OrcWarlord(String weapon) {
 | 
			
		||||
    this.weapon = weapon;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  public OrcWarlord(OrcWarlord orcWarlord) {
 | 
			
		||||
    this.weapon = orcWarlord.weapon;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Warlord clone() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcWarlord();
 | 
			
		||||
  public OrcWarlord copy() throws CloneNotSupportedException {
 | 
			
		||||
    return new OrcWarlord(this);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public String toString() {
 | 
			
		||||
    return "Orcish warlord";
 | 
			
		||||
    return "Orcish warlord attacks with " + weapon;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,6 @@ package com.iluwatar.prototype;
 | 
			
		||||
 */
 | 
			
		||||
public abstract class Prototype implements Cloneable {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public abstract Object clone() throws CloneNotSupportedException;
 | 
			
		||||
  public abstract Object copy() throws CloneNotSupportedException;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,6 @@ package com.iluwatar.prototype;
 | 
			
		||||
public abstract class Warlord extends Prototype {
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public abstract Warlord clone() throws CloneNotSupportedException;
 | 
			
		||||
  public abstract Warlord copy() throws CloneNotSupportedException;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -43,18 +43,18 @@ public class HeroFactoryImplTest {
 | 
			
		||||
    final Warlord warlord = mock(Warlord.class);
 | 
			
		||||
    final Beast beast = mock(Beast.class);
 | 
			
		||||
 | 
			
		||||
    when(mage.clone()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
    when(warlord.clone()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
    when(beast.clone()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
    when(mage.copy()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
    when(warlord.copy()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
    when(beast.copy()).thenThrow(CloneNotSupportedException.class);
 | 
			
		||||
 | 
			
		||||
    final HeroFactoryImpl factory = new HeroFactoryImpl(mage, warlord, beast);
 | 
			
		||||
    assertNull(factory.createMage());
 | 
			
		||||
    assertNull(factory.createWarlord());
 | 
			
		||||
    assertNull(factory.createBeast());
 | 
			
		||||
 | 
			
		||||
    verify(mage).clone();
 | 
			
		||||
    verify(warlord).clone();
 | 
			
		||||
    verify(beast).clone();
 | 
			
		||||
    verify(mage).copy();
 | 
			
		||||
    verify(warlord).copy();
 | 
			
		||||
    verify(beast).copy();
 | 
			
		||||
    verifyNoMoreInteractions(mage, warlord, beast);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,12 +41,12 @@ import static org.junit.jupiter.api.Assertions.assertSame;
 | 
			
		||||
public class PrototypeTest<P extends Prototype> {
 | 
			
		||||
  static Collection<Object[]> dataProvider() {
 | 
			
		||||
    return Arrays.asList(
 | 
			
		||||
            new Object[]{new OrcBeast(), "Orcish wolf"},
 | 
			
		||||
            new Object[]{new OrcMage(), "Orcish mage"},
 | 
			
		||||
            new Object[]{new OrcWarlord(), "Orcish warlord"},
 | 
			
		||||
            new Object[]{new ElfBeast(), "Elven eagle"},
 | 
			
		||||
            new Object[]{new ElfMage(), "Elven mage"},
 | 
			
		||||
            new Object[]{new ElfWarlord(), "Elven warlord"}
 | 
			
		||||
            new Object[]{new OrcBeast("axe"), "Orcish wolf attacks with axe"},
 | 
			
		||||
            new Object[]{new OrcMage("sword"), "Orcish mage attacks with sword"},
 | 
			
		||||
            new Object[]{new OrcWarlord("laser"), "Orcish warlord attacks with laser"},
 | 
			
		||||
            new Object[]{new ElfBeast("cooking"), "Elven eagle helps in cooking"},
 | 
			
		||||
            new Object[]{new ElfMage("cleaning"), "Elven mage helps in cleaning"},
 | 
			
		||||
            new Object[]{new ElfWarlord("protecting"), "Elven warlord helps in protecting"}
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +55,7 @@ public class PrototypeTest<P extends Prototype> {
 | 
			
		||||
  public void testPrototype(P testedPrototype, String expectedToString) throws Exception {
 | 
			
		||||
    assertEquals(expectedToString, testedPrototype.toString());
 | 
			
		||||
 | 
			
		||||
    final Object clone = testedPrototype.clone();
 | 
			
		||||
    final Object clone = testedPrototype.copy();
 | 
			
		||||
    assertNotNull(clone);
 | 
			
		||||
    assertNotSame(clone, testedPrototype);
 | 
			
		||||
    assertSame(testedPrototype.getClass(), clone.getClass());
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user