设计模式

设计模式-原型模式

2020-05-16  本文已影响0人  isLJli

原型设计模式的定义

用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
这里重点在拷贝,就像电脑的拷贝和复制粘贴。

java的浅拷贝和深拷贝的区别
浅拷贝:类里的类对象是共同一个引用。
深拷贝:类里的类对象不是同一个引用
系统自带的拷贝:实现Cloneable,复写clone()方法。

原型模式的例子:

UML图

UML图
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

上一篇 下一篇

猜你喜欢

热点阅读