原型模式
定义
原型模式是一种创建型模式.原型模式的本质是克隆.当我们需要去克隆一个类时,一般做法是首先我们先new一个相同的对象实例,然后为该对象实例的所有属性赋值成相同的已有对象的属性值.实现这种克隆的前提是我们对已有类具有充分的了解,且这种克隆方式的缺点是当待克隆类比较复杂时,我们克隆的代码量会增大.为此引出了原型模式.原型模式将克隆的任务交给了待克隆对象本身,有待克隆对象实现某个克隆接口,然后重写该接口的克隆方法.所有需要克隆该对象的类只需要实现克隆借口,然后调用待克隆对象的克隆方法即可.
原型模式可以在无须了解一个类的前提下去获取到该类的克隆实例
原型模式的实现
Java中的Cloneable
在Java中有一个自带的Cloneable接口实现了原型模式,我们只需要实现该接口并重写clone方法即可实现原型模式
public class Sheep implements Cloneable{
// 以克隆羊为例实现原型模式
private String name;
private String color;
private int age;
public Sheep(String name, String color, int age) {
this.name = name;
this.color = color;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Sheep sheep = null;
sheep =(Sheep)super.clone();
return sheep;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", age=" + age +
'}';
}
}
自主实现的原型模式
我们也可以通过在待克隆对象中通过new的方式实现原型模式
// 克隆接口
public abstract class Shape {
public int x;
public int y;
public String color;
public Shape(){
}
public Shape(Shape shape){
if(shape != null){
this.x = shape.x;
this.y = shape.y;
this.color = shape.color;
}
}
public abstract Shape clone();
}
// 继承克隆接口并重写克隆方法
public class Rectangle extends Shape{
public Rectangle(){
}
public Rectangle(Rectangle rectangle){
super(rectangle);
}
@Override
public Shape clone() {
return new Rectangle(this);
}
}
深拷贝
深拷贝意味着在堆上创建一个新的对象,然后将待克隆对象的所有属性复制一份给新的对象.深拷贝得到的克隆对象和带克隆对象本身是两个完全独立的对象.
在Java中的clone()方法即为深拷贝
public static void main(String[] args) throws CloneNotSupportedException {
Sheep sheep = new Sheep("first","white",8);
Sheep sheep1 = (Sheep)sheep.clone();
Sheep sheep2 = (Sheep)sheep.clone();
System.out.println(sheep1 == sheep); // 返回的结果为false
}
在Java中除了clone()方法可以实现深拷贝之外,还可以通过序列化/反序列化的方式来实现深拷贝
class Clone implements Serializable{
public Object deepClone(){
ByteArrayOutputStream bos = null;
ByteArrayInputSream bis = null;
ObjectArrayOutputStream oos = null;
ObjectArrayInputStream pis = null;
try{
bos = new ByteArrayOutputStream();
oos = new ObjectArrayOutputStream(bos);
oos.writeObject(this); // 将对象序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectArrayInputStream(bis);
Clone copyObj = (Clone)ois.readObject(); // 反序列化得到对象的深拷贝
return copyObj
}catch(Exception e){
// 打印异常
}finally{
// 关闭文件流
}
return null;
}
}
原型模式的适用性
当你需要复制一些对象,但又希望代码可以独立于对象所属的具体类或对对象所属的具体类不甚了解时可以考虑使用原型模式,如使用第三方所提供的代码
建造者模式
定义
建造者模式是一种创建型模式,也被称为生成器模式.建造者模式专注于一个复杂对象的构建过程.将产品的使用与创建两个过程分离开来,降低代码的耦合性.
结构
建造者模式由4部分组成,分别是Product,Builder,Concentrate Builder,Director.其中Product即为产品类,包括产品的各个属性;Builder即为将创建过程单独分离出来的抽象创建接口.用户通过调用抽象接口来创建产品.在抽象创建接口中要描述一类产品的通用创建方法,比如对于一辆车而言,创建过程可以分为创建车轮,创建发动机,创建车身等等.Concentrate Builder即为实现抽象创建接口的具体创建子类.而Director通过组合Builder来协助用户使用产品.
适用性
- 建造者模式可以用来代替"伸缩构造函数",即带有大量形参的构造函数.
- 当专注于创建某些产品的不同表示时,可以使用建造者模式
实现步骤
- 首先需要确保所有产品都具有通用的创建步骤
- 在通用创建接口(Builder)中声明这些步骤
- 创建具体创建子类来实现通用创建接口中的步骤以及获取对应产品的方法(getResult)
- 可以考虑创建一个Director,通过组合Builder来协助用户使用产品
- 客户端可以通过调用Director来创建和使用一些常见的产品,当然也可以通过直接调用通用抽象接口的方式来创建一些"独特"的产品