设计模式-原型模式
2020-05-16 本文已影响0人
isLJli
原型设计模式的定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
这里重点在拷贝,就像电脑的拷贝和复制粘贴。
java的浅拷贝和深拷贝的区别
浅拷贝:类里的类对象是共同一个引用。
深拷贝:类里的类对象不是同一个引用
系统自带的拷贝:实现Cloneable,复写clone()方法。
原型模式的例子:
UML图
![](https://img.haomeiwen.com/i22650779/ab4d86e776ccdc63.jpg)
public abstract class IBox implements Cloneable {
abstract void setNumber(int number); //设置数量
abstract int getNumber();
@NonNull
@Override
protected IBox clone() throws CloneNotSupportedException {
return (IBox) super.clone();
}
}
public class CarPartBox extends IBox {
private int number;
private String name;
private String carBrand;
@Override
public void setNumber(int number) {
this.number = number;
}
@Override
public int getNumber() {
return number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCarBrand() {
return carBrand;
}
public void setCarBrand(String carBrand) {
this.carBrand = carBrand;
}
}
public class PlasticClampBox extends IBox {
private int number;
private String name;
@Override
public void setNumber(int number) {
this.number = number;
}
@Override
public int getNumber() {
return number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class TruckCar {
public IBox mIBox;
public void addBox(IBox box){
this.mIBox = box;
}
public IBox remove(){
return mIBox;
}
}
public class SplitService {
public static List<TruckCar> splitBox(IBox box) {
List<TruckCar> carList = new ArrayList<>();
while (box.getNumber() > 200) {
IBox newBox = null;
try {
newBox = box.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
newBox.setNumber(200);
TruckCar truckCar = new TruckCar();
truckCar.addBox(newBox);
carList.add(truckCar);
box.setNumber(box.getNumber() - 200);
}
TruckCar truckCar = new TruckCar();
truckCar.addBox(box);
carList.add(truckCar);
return carList;
}
}
浅拷贝的实现方式
拷贝构造方法实现浅拷贝
/* 拷贝构造方法实现浅拷贝 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.ff);
Person.Address mAddress = new Person.Address("广州市");
Person person1 = new Person(mAddress, "tony");
Person person2 = new Person(person1);
System.out.println("p1是" + person1.toString());
System.out.println("p2是" + person2.toString());
person1.setName("小傻瓜");
mAddress.setAddress("深圳市");
System.out.println("修改后的p1是"+person1.toString());
System.out.println("修改后的p2是"+person2.toString());
}
public class Person {
private String name;
private Address mAddress;
public Person(Address address, String name) {
this.mAddress = address;
this.name = name;
}
public Person(Person person){
this.mAddress = person.mAddress;
this.name = person.name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return mAddress;
}
public void setAddress(Address address) {
mAddress = address;
}
@NonNull
@Override
public String toString() {
String s ="姓名="+name+",地址="+mAddress.address;
return s;
}
public static class Address {
private String address;
public Address(String address){
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
}
打印结果:
p1是姓名=tony,地址=广州市
p2是姓名=tony,地址=广州市
修改后的p1是姓名=小傻瓜,地址=深圳市
修改后的p2是姓名=tony,地址=深圳市
通过重写clone方法来实现深拷贝
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.ff);
Person.Address mAddress = new Person.Address("广州市");
Person person1 = new Person(mAddress, "tony");
Person person2 = new Person(person1);
System.out.println("p1是" + person1.toString());
System.out.println("p2是" + person2.toString());
person1.setName("小傻瓜");
mAddress.setAddress("深圳市");
System.out.println("修改后的p1是"+person1.toString());
System.out.println("修改后的p2是"+person2.toString());
}
public class Person implements Cloneable{
private String name;
private Address mAddress;
public Person(Address address, String name) {
this.mAddress = address;
this.name = name;
}
public Person(Person person){
this.mAddress = person.mAddress;
this.name = person.name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return mAddress;
}
public void setAddress(Address address) {
mAddress = address;
}
@NonNull
@Override
protected Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
@NonNull
@Override
public String toString() {
String s ="姓名="+name+",地址="+mAddress.address;
return s;
}
public static class Address {
private String address;
public Address(String address){
this.address = address;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
}
打印结果:
p1是姓名=tony,地址=广州市
p2是姓名=tony,地址=广州市
修改后的p1是姓名=小傻瓜,地址=深圳市
修改后的p2是姓名=tony,地址=深圳市
深拷贝的实现方式
通过重写clone方法来实现深拷贝
public class DeepCopy {
public static void main(String[] args) {
Age a=new Age(20);
Student stu1=new Student("摇头耶稣",a,175);
//通过调用重写后的clone方法进行浅拷贝
Student stu2=(Student)stu1.clone();
System.out.println(stu1.toString());
System.out.println(stu2.toString());
System.out.println();
//尝试修改stu1中的各属性,观察stu2的属性有没有变化
stu1.setName("大傻子");
//改变age这个引用类型的成员变量的值
a.setAge(99);
//stu1.setaAge(new Age(99)); 使用这种方式修改age属性值的话,stu2是不会跟着改变的。因为创建了一个新的Age类对象而不是改变原对象的实例值
stu1.setLength(216);
System.out.println(stu1.toString());
System.out.println(stu2.toString());
}
}
/*
* 创建年龄类
*/
class Age implements Cloneable{
//年龄类的成员变量(属性)
private int age;
//构造方法
public Age(int age) {
this.age=age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return this.age+"";
}
//重写Object的clone方法
public Object clone() {
Object obj=null;
try {
obj=super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
}
/*
* 创建学生类
*/
class Student implements Cloneable{
//学生类的成员变量(属性),其中一个属性为类的对象
private String name;
private Age aage;
private int length;
//构造方法,其中一个参数为另一个类的对象
public Student(String name,Age a,int length) {
this.name=name;
this.aage=a;
this.length=length;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Age getaAge() {
return this.aage;
}
public void setaAge(Age age) {
this.aage=age;
}
public int getLength() {
return this.length;
}
public void setLength(int length) {
this.length=length;
}
public String toString() {
return "姓名是: "+this.getName()+", 年龄为: "+this.getaAge().toString()+", 长度是: "+this.getLength();
}
//重写Object类的clone方法
public Object clone() {
Object obj=null;
//调用Object类的clone方法——浅拷贝
try {
obj= super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//调用Age类的clone方法进行深拷贝
//先将obj转化为学生类实例
Student stu=(Student)obj;
//学生类实例的Age对象属性,调用其clone方法进行拷贝
stu.aage=(Age)stu.getaAge().clone();
return obj;
}
}
姓名是: 摇头耶稣, 年龄为: 20, 长度是: 175
姓名是: 摇头耶稣, 年龄为: 20, 长度是: 175
姓名是: 大傻子, 年龄为: 99, 长度是: 216
姓名是: 摇头耶稣, 年龄为: 20, 长度是: 175