设计模式(五):原型模式
本文所使用的注解均来自lombok(小辣椒)的使用,包括
···@Data 注解包含 get,set,toString等方法。
···@AllArgsConstructor 注解 创建了一个全参(name,sex,task,hobby)构造函数。
一.猴子
先来一个经典的入门的程序。使用private定义几个属性
1 package com.cllover.old; 2 3 import lombok.AllArgsConstructor; 4 import lombok.Data; 5 import lombok.Getter; 6 7 /* 8 * 猴类 9 * 10 * */ 11 12 13 @Data //使用lombok注解代替set get等方法 14 @AllArgsConstructor //全参构造函数 15 public class Monkey { 16 17 //我有名字 18 private String name; 19 //我有性别 20 private String sex; 21 //我有任务 22 private String task; 23 //我有喜欢的东西 24 private String hobby; 25 26 27 }
创建一个客户端去使用这个类。
1 package com.cllover.old; 2 3 public class Client { 4 public static void main(String[] args) { 5 Monkey monkey = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 6 System.out.println(monkey); 7 8 } 9 10 }
result: Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
创建对象的同时,并赋值。随后输出(result)
·····注意:这种写法是由于使用 了@AllArgsConstructor注解在monkey类中创建了全参构造函数后,可以直接赋值。
看过西游记的人都知道,孙悟空不仅可以72变化,还可以拽很多毛便可以复制很多的分身。
于是,根据这个程序,创建多个monkey对象,给出复制功能。如下
1 package com.cllover.old; 2 3 public class Client { 4 public static void main(String[] args) { 5 Monkey monkey = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 6 Monkey monkeyClone1 = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 7 Monkey monkeyClone2 = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 8 Monkey monkeyClone3 = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 9 Monkey monkeyClone4 = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 10 System.out.println(monkey); 11 System.out.println("monkeyClone1:"+monkeyClone1); 12 System.out.println("monkeyClone2:"+monkeyClone2); 13 System.out.println("monkeyClone3:"+monkeyClone3); 14 System.out.println("monkeyClone4:"+monkeyClone4); 15 16 } 17 18 }
result:
Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
monkeyClone1:Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
monkeyClone2:Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
monkeyClone3:Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
monkeyClone4:Monkey(name=孙悟空, sex=公, task=喜欢吃香蕉, hobby=斩妖除魔)
结果本体复制体都出现了,程序是问题了,但是这样做,不仅出现了很多重复代码,如果不慎将当中的其中一个对象的赋值内容改变,就不再是当初的猴子一摸一样的复制体。
缺点:
-
代码重复冗余。
-
改变了其中一个赋值就不再是复制的结果,违背了初衷。
-
复制的细节被暴露
二.原型模式
······在此相关功能下,原型模式应用而生。
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型,创建新的对象。
允许对象去创建一个新的可以定制的对象,而无需知道创建的细节。要创建的对象通过请求原型拷贝来创建实例,使用方法为.clone().
······使用原型模式对以上程序进行改造。
实现与Cloneable接口,并实现Clone方法的复写。
1 package com.cllover.old; 2 3 import lombok.AllArgsConstructor; 4 import lombok.Data; 5 import lombok.Getter; 6 7 import java.io.Closeable; 8 import java.io.IOException; 9 import java.util.ArrayList; 10 import java.util.List; 11 12 /* 13 * 猴类 14 * 15 * */ 16 17 18 @Data //使用lombok注解代替set get等方法 19 @AllArgsConstructor //全参构造函数 20 public class Monkey implements Cloneable { 21 22 //我有名字 23 private String name; 24 //我有性别 25 private String sex; 26 //我有任务 27 private String task; 28 //我有喜欢的东西 29 private String hobby; 30
// 增加复写一个类 31 @Override 32 protected Object clone() throws CloneNotSupportedException { 33 return (Monkey)super.clone(); 34 } 35 }
client:
1 package com.cllover.old; 2 3 import java.util.ArrayList; 4 5 public class Client { 6 public static void main(String[] args) { 7 Monkey monkey = new Monkey("孙悟空","公","喜欢吃香蕉","斩妖除魔"); 8 9 Monkey clone = null; 10 Monkey clone2 = null; 11 Monkey clone3 = null; 12 try { 13 clone = (Monkey) monkey.clone(); 14 clone2 = (Monkey) monkey.clone(); 15 clone3 = (Monkey) monkey.clone(); 16 17 } catch (CloneNotSupportedException e) { 18 e.printStackTrace(); 19 } 20 21 System.out.println(monkey); 22 System.out.println(clone); 23 System.out.println(clone2); 24 System.out.println(clone3); 25 26 27 } 28 29 }
由于clone方法复制的结果是一个Object类型,所以必须进行强转。