一、原型模式
原型模式指原型实例指定创建对象的种类,通过拷贝这些原型对象创建新的对象。原型模式不需要知道任何创建的细节,不调用构造函数,而且原型模式的性能比直接new一个对象性能高。
1、基于浅拷贝的原型模式
所谓浅拷贝即拷贝出一个对象,但是拷贝出来的对象属性指向的还是原来的内存空间。浅拷贝直接使用默认生成的clone方法即可。
能力表类:
public class CapacityTable implements Cloneable {
private int attackValue;
private int defenseValue;
public int getAttackValue() {
return attackValue;
}
public void setAttackValue(int attackValue) {
this.attackValue = attackValue;
}
public int getDefenseValue() {
return defenseValue;
}
public void setDefenseValue(int defenseValue) {
this.defenseValue = defenseValue;
}
public CapacityTable(int attackValue, int defenseValue) {
this.attackValue = attackValue;
this.defenseValue = defenseValue;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
战神类:
public class GodOfWar implements Cloneable {
private CapacityTable capacity;
private int age;
public CapacityTable getCapacity() {
return capacity;
}
public void setCapacity(CapacityTable capacity) {
this.capacity = capacity;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public GodOfWar(CapacityTable capacity, int age) {
this.capacity = capacity;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试代码:
GodOfWar hero = new GodOfWar(new CapacityTable(20, 20), 23);
GodOfWar copy = (GodOfWar) hero.clone();
System.out.println(hero);
System.out.println(copy);
System.out.println(hero.getCapacity());
System.out.println(copy.getCapacity());
System.out.println(copy.getCapacity() == hero.getCapacity());
运行结果(结果表明两个对象中的capacity属性指向的是一块内存空间):
2、基于逐层实现clone方法深拷贝的原型模式
所谓深拷贝就是拷贝出一个对象,而且对象里面的所有属性指向的也是不同的内存空间。
深拷贝需要手动一层层的实现clone方法。
修改战神类代码的clone
方法如下:
@Override
protected Object clone() throws CloneNotSupportedException {
GodOfWar godOfWar = (GodOfWar) super.clone();
if (godOfWar != null) {
godOfWar.capacity = (CapacityTable) capacity.clone();
}
return godOfWar;
}
还是使用上面的测试代码,结果如下图(可见已经达到了深拷贝的目的):
3、基于序列化和反序列化实现深拷贝的原型模式
将原来的能力表类实现Serializable
接口,并改写战神类如下:
public class GodOfWar implements Cloneable, Serializable {
private CapacityTable capacity;
private int age;
public CapacityTable getCapacity() {
return capacity;
}
public void setCapacity(CapacityTable capacity) {
this.capacity = capacity;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public GodOfWar(CapacityTable capacity, int age) {
this.capacity = capacity;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
GodOfWar godOfWar = (GodOfWar) super.clone();
if (godOfWar != null) {
godOfWar.capacity = (CapacityTable) capacity.clone();
}
return godOfWar;
}
public Object deepClone() throws IOException, ClassNotFoundException {
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
测试代码:
GodOfWar hero = new GodOfWar(new CapacityTable(20, 20), 23);
GodOfWar copy = (GodOfWar) hero.deepClone();
System.out.println(hero);
System.out.println(copy);
System.out.println(hero.getCapacity());
System.out.println(copy.getCapacity());
System.out.println(copy.getCapacity() == hero.getCapacity());
测试结果(可见已经达到了深拷贝的目的):
二、建造者模式
建造者模式即使用多个简单的对象一步一步构建成一个复杂的对象,可以将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
1、普通的建造者模式
要建造的类:
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public String getBuildA() {
return buildA;
}
public void setBuildA(String buildA) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' + super.toString() +
'}';
}
}
抽象的建造者类:
public abstract class Builder {
abstract void buildA(); //地基
abstract void buildB(); //钢筋工程
abstract void buildC(); //铺电线
abstract void buildD(); //粉刷
abstract Product getProduct(); //完工-获取产品
}
具体的建造者类:
public class ConcreteBuilder extends Builder {
private Product product;
public ConcreteBuilder() {
product = new Product();
}
@Override
void buildA() {
product.setBuildA("地基");
}
@Override
void buildB() {
product.setBuildB("钢筋工程");
}
@Override
void buildC() {
product.setBuildC("铺电线");
}
@Override
void buildD() {
product.setBuildD("粉刷");
}
@Override
Product getProduct() {
return product;
}
}
指导者类:
public class Director {
public Product create(Builder builder) {
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
测试代码:
Director director = new Director();
Product product = director.create(new ConcreteBuilder());
System.out.println(product);
测试结果:
2、链式调用的建造者模式
使用公共的静态内部类完成链式调用的建造。
要建造的类:
public class Product {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public Product(ProductBuilder builder) {
this.buildA = builder.buildA;
this.buildB = builder.buildB;
this.buildC = builder.buildC;
this.buildD = builder.buildD;
}
public static class ProductBuilder {
private String buildA;
private String buildB;
private String buildC;
private String buildD;
public ProductBuilder setBuildA(String buildA) {
this.buildA = buildA;
return this;
}
public ProductBuilder setBuildB(String buildB) {
this.buildB = buildB;
return this;
}
public ProductBuilder setBuildC(String buildC) {
this.buildC = buildC;
return this;
}
public ProductBuilder setBuildD(String buildD) {
this.buildD = buildD;
return this;
}
public Product build() {
return new Product(this);
}
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' + super.toString() +
'}';
}
}
测试代码:
Product product = new Product.ProductBuilder()
.setBuildA("地基")
.setBuildB("钢筋工程")
.setBuildC("铺电线")
.setBuildD("粉刷")
.build();
System.out.println(product);
测试结果: