To learn the concept of Interface and the reusability of objects, which are important in object orientation ["Introduction to design patterns learned in Java language"](https://www.amazon.co.jp/%E5%A2%97% E8% A3% 9C% E6% 94% B9% E8% A8% 82% E7% 89% 88Java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6% E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5% 85% A5% E9% 96% 80-% E7% B5% 90% E5% 9F% 8E-% E6% B5% A9 / dp / 4797327030 / ref = sr_1_1? __mk_ja_JP =% E3% 82% AB % E3% 82% BF% E3% 82% AB% E3% 83% 8A & keywords = java% E8% A8% 80% E8% AA% 9E% E3% 81% A7% E5% AD% A6% E3% 81% B6 % E3% 83% 87% E3% 82% B6% E3% 82% A4% E3% 83% B3% E3% 83% 91% E3% 82% BF% E3% 83% BC% E3% 83% B3% E5 I learned about% 85% A5% E9% 96% 80 & qid = 1559563427 & s = gateway & sr = 8-1) and decided to write in Java and then in kotlin. This time I will write about Prototype.
A pattern that is based on a class when creating an instance, but copies an existing instance and replicates it as another instance.
There are merits in the following cases.
- When there are too many types to put together in a class
In addition, the sample code provides a pattern to create a new instance based on the prototype instance.
An instance of a subclass that inherits the Product class in the interface that inherits Cloneable is the class to be copied.
In Kotlin it will be java.lang.NoClassDefFoundError
if Cloneable is implemented in the Product interface. Apparently it can't be implemented in the interface, and it is the class that inherits Cloneable.
We also confirmed that it can be implemented in the case of a subclass of an abstract class that inherits Cloneable.
Reference: Design pattern with Kotlin Prototype 06 Design Model-kotlin-Recovery Prototype
Product.java
interface Product extends Cloneable {
public abstract void use(String s);
public abstract Product createClone();
}
Product.kt
interface Product {
fun use(s: String)
fun createClone(): Product
}
For Product abstract class
Product.kt
abstract class Product(): Cloneable {
abstract fun use(s: String)
abstract fun createClone(): Product
}
It is a class that duplicates an instance using createClone, and if you register it, it will be a class that can be duplicated at any time.
HashMap can be obtained by either showcase.get ()
or showcase []
.
In kotlin, val a: String = null
will result in a compile error, and Null is not allowed by default. If you specify?, Null can be handled. Also, if the specified p is Null, createClone will not be executed and Null will be returned.
Reference: [Kotlin] [Java] Kotlin Java comparison memo [Null Safety] Kotlin Java Comparison Memo Correct Null Safety Usage Try "Introduction to Design Patterns Learned in Java Language" with Kotlin (Prototype)
@htsign Thank you for your review.
Originally I wanted to declare a variable p of type Product outside the block of the try statement in the subclass of Product
I assigned Null
and specified?
, But I modified it to delay initialization using lateinit
and modified it so that it does not handle Null.
So the createClone ()
of the Product
interface also returns the return value from Product?
To Product
.
Manager.java
class Manager {
private HashMap showcase = new HashMap();
public void register(String name, Product proto) {
showcase.put(name, proto);
}
public Product create(String protoname) {
Product p = (Product)showcase.get(protoname);
return p.createClone();
}
}
Manager.kt
class Manager {
private var showcase: MutableMap<String, Product> = mutableMapOf()
fun register(name: String, proto: Product){
showcase.put(name, proto)
}
fun create(protoname: String): Product?{
val p = showcase[protoname] as Product
return p?.createClone()
}
}
Fix Manager.kt
class Manager {
private var showcase: MutableMap<String, Product> = mutableMapOf()
fun register(name: String, proto: Product){
showcase.put(name, proto)
}
fun create(protoname: String): Product{
val p = showcase[protoname] as Product
return p.createClone()
}
}
This class displays a character string surrounded by a border.
The Cloneable mentioned earlier needs to be implemented in a subclass of Product.
Also, since the clone method can only be called from your own class (and subclass), if you want to duplicate at the request of another class (Manager), call clone with another method such as createClone ()
. It is necessary.
MessageBox.java
class MessageBox implements Product {
private char decochar;
public MessageBox(char decochar) {
this.decochar = decochar;
}
public void use(String s) {
int length = s.getBytes().length;
for (int i = 0; i < length + 4; i++) {
System.out.print(decochar);
}
System.out.println("");
System.out.println(String.format("%s %s %s", decochar, s, decochar));
for (int i = 0; i < length + 4; i++) {
System.out.print(decochar);
}
System.out.println("");
}
public Product createClone(){
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
MessageBox.kt
class MessageBox(private val d: Char): Product, Cloneable{
override fun use(s: String){
val length = s.toByteArray().size
for (i: Int in 1..length + 4) print(d)
println("")
println("%s %s %s".format(d, s, d))
for (i: Int in 1..length + 4) print(d)
println("")
}
override fun createClone(): Product?{
var p: Product? = null
try {
p = clone() as Product
}catch (e:CloneNotSupportedException){
e.printStackTrace()
}
return p
}
}
Modified MessageBox.kt
class MessageBox(private val d: Char): Product, Cloneable{
override fun use(s: String){
val length = s.toByteArray().size
for (i: Int in 1..length + 4) print(d)
println("")
println("%s %s %s".format(d, s, d))
for (i: Int in 1..length + 4) print(d)
println("")
}
override fun createClone(): Product{
lateinit var p: Product
try {
p = clone() as Product
}catch (e:CloneNotSupportedException){
e.printStackTrace()
}
return p
}
}
This class is displayed by underlining the character string.
UnderlinePen.java
class UnderlinePen implements Product {
private char ulchar;
public UnderlinePen(char ulchar) {
this.ulchar = ulchar;
}
public void use(String s) {
int length = s.getBytes().length;
System.out.println(String.format("\"%s\"", s));
System.out.print(" ");
for (int i = 0; i < length; i++) {
System.out.print(ulchar);
}
System.out.println("");
}
public Product createClone() {
Product p = null;
try {
p = (Product)clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return p;
}
}
UnderlinePen.kt
class UnderLinePen(ulchar: Char): Product, Cloneable{
private val u = ulchar
override fun use(s: String) {
val length = s.toByteArray().size
println("\"%s\"".format(s))
print(" ")
for (i: Int in 1..length) print(u)
println("")
}
override fun createClone(): Product? {
var p: Product? = null
try {
p = clone() as Product
}catch (e: CloneNotSupportedException){
e.printStackTrace()
}
return p
}
}
Fixed Underline Pen.kt
class UnderLinePen(ulchar: Char): Product, Cloneable{
private val u = ulchar
override fun use(s: String) {
val length = s.toByteArray().size
println("\"%s\"".format(s))
print(" ")
for (i: Int in 1..length) print(u)
println("")
}
override fun createClone(): Product {
lateinit var p: Product
try {
p = clone() as Product
}catch (e: CloneNotSupportedException){
e.printStackTrace()
}
return p
}
}
PrototypeSample.java
public class PrototypeSample {
public static void main(String[] args) {
Manager manager = new Manager();
UnderlinePen upen = new UnderlinePen('~');
MessageBox mbox = new MessageBox('*');
MessageBox sbox = new MessageBox('/');
manager.register("strong message", upen);
manager.register("warning box", mbox);
manager.register("slash box", sbox);
Product p1 = manager.create("strong message");
Product p2 = manager.create("warning box");
Product p3 = manager.create("slash box");
p1.use("Hello, World.");
p2.use("Hello, World.");
p3.use("Hello, World.");
}
}
PrototypeSample.kt
fun main(args: Array<String>) {
val manager = Manager()
val upen = UnderLinePen('~')
val mbox = MessageBox('*')
val sbox = MessageBox('/')
manager.register("strong message", upen)
manager.register("warning box", mbox)
manager.register("slash box", sbox)
val p1 = manager.create("strong message")
val p2 = manager.create("warning box")
val p3 = manager.create("slash box")
p1?.use("Hellow, World.")
p2?.use("Hellow, World.")
p3?.use("Hellow, World.")
}
Modified Prototype Sample.kt
fun main(args: Array<String>) {
val manager = Manager()
val upen = UnderLinePen('~')
val mbox = MessageBox('*')
val sbox = MessageBox('/')
manager.register("strong message", upen)
manager.register("warning box", mbox)
manager.register("slash box", sbox)
val p1 = manager.create("strong message")
val p2 = manager.create("warning box")
val p3 = manager.create("slash box")
p1.use("Hellow, World.")
p2.use("Hellow, World.")
p3.use("Hellow, World.")
}
Execution result
"Hello, World."
~~~~~~~~~~~~~
*****************
* Hello, World. *
*****************
/////////////////
/ Hello, World. /
/////////////////
I also investigated why + clone is necessary in the first place (Reference: About Java clone () method) Inherited I learned that the clone method was designed to copy the instance as it is because it behaves unintentionally when creating an instance in a subclass or the like.
String # getBytes
withtoByteArray ()
shallow copy
(the reference value is copied instead of the reference value of the field destination), so if you rewrite the instance field, you may unintentionally rewrite the clone source field, sodeep copy I learned that it is necessary to override and add processing when
(copying to the value of the reference destination of the field destination).marker interface
.It was very easy to read and understand by referring to the following.
How to write Java String # getBytes in Kotlin? Design pattern with Kotlin Prototype 06 Design Model-kotlin-Recovery Prototype [Kotlin] [Java] Kotlin Java comparison memo [Null Safety] Kotlin Java Comparison Memo Correct Null Safety Usage Try "Introduction to Design Patterns Learned in Java Language" with Kotlin (Prototype)
Also, the following blog explained in detail about clone ()
, which was a great learning experience.
About the Java clone () method
Recommended Posts