原型模式
概述
用一个已经创建的实例体为原型,通过复制该原型对象来创建一个和原型对象相同的对象。
结构
原型模式包含如下角色:
- 抽象原型类:规定了具体原型对象必须实现的的clone ()方法。
- 具体原型类:实现抽象原型类的clone ()方法,它是可被复制的对象。
- 访问类:使用具体原型类中的clone ()方法来复制新的对象。
接口类图如下:
实现
原型模式的克隆分为浅克隆和深克隆。
浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。
深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。
Java中的object类中提供了clone()方法来实现浅克隆。Cloneable接口是上面的类图中的抽象原型类,而实现了Cloneable接口的子实现类就是具体的原型类。代码如下:
Realizetype(具体的原型类):
public class Realizetype implements Cloneable{
public Realizetype() {
System.out.println("具体的原型对象创建完成");
}
@Override
public Realizetype clone() throws CloneNotSupportedException {
System.out.println("具体原型复制成功");
return (Realizetype) super.clone();
}
}
测试类:
public class client {
public static void main(String[] args) throws CloneNotSupportedException {
//创建一个原型对象
Realizetype realizetype = new Realizetype();
Realizetype clone = realizetype.clone();
System.out.println("原型对象和克隆出来的是否是同一个对象?"+(realizetype == clone));
}
}
案例
用原型模式生成"三好学生"奖状
同一学校的"三好学生"奖状除了获奖人姓名不同,其他都相同,可以使用原型模式复制多个"三好学生奖状出来,然后在修改奖状上的名字即可。
类图如下:
学生类
public class Student implements Cloneable{
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
奖状类
public class Citation implements Cloneable{
private Student student;
public void setStudent(Student student) {
this.student = student;
}
public Student getStudent() {
return student;
}
@Override
public Citation clone() throws CloneNotSupportedException {
Citation citation = (Citation) super.clone();
citation.student = student.clone();
return citation;
}
public void show(){
System.out.println(student.getName()+ "同学:在2021学年第一学期中表现优秀被评为三好学生,特发此状!");
}
}
测试类
public class client {
public static void main(String[] args) throws CloneNotSupportedException {
Citation citation = new Citation();
Student student1 = new Student("李洛", 18);
citation.setStudent(student1);
Citation clone = citation.clone();
clone.getStudent().setName("牧尘");
citation.show();
clone.show();
}
}
建造者模式
概述
- 分离了部件的构造(由Builder来负责)和装配(由Director负责)。从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况。
- 由于实现了构建和装配的解耦。不同的构建器,相同的装配,也可以做出不同的对象;相同的构建器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
- 建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节。
结构
建造者(Builder)模式包含如下角色:
- 抽象建造者类(Builder):这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的对象部件的创建。
- 具体建造者类(ConcreteBuilder):实现Builder接口,完成复杂产品的各个部件的具体创建方法。在构造过程完成后,提供产品的实例。
- 产品类(Product)︰要创建的复杂对象。
- 指挥者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
类图如下:
实例
创建共享单车
生产自行车是一个复杂的过程,它包含了车架,车座等组件的生产。而车架又有碳纤维,铝合金等材质的,车座有橡胶,真皮等材质。对于自行车的生产就可以使用建造者模式。
这里Bike是产品,包含车架,车座等组件; Builder是抽象建造者,MobikeBuilder和ofoBuilder是具体的建造者; Director是指挥者。类图如下:
产品类
//产品对象
public class Bike {
private String frame;//车架
private String seat;//车座
public String getFrame() {
return frame;
}
public void setFrame(String frame) {
this.frame = frame;
}
public String getSeat() {
return seat;
}
public void setSeat(String seat) {
this.seat = seat;
}
}
抽象建造者类
public abstract class Builder {
//声明Bike类型的变量,并进行赋值
protected Bike bike = new Bike();
public abstract void builderFrame();
public abstract void builderSeat();
//构建自行车的方法
public abstract Bike createBike();
}
具体建造者类
public class MobileBuilder extends Builder{
@Override
public void builderFrame() {
bike.setFrame("碳纤维");
}
@Override
public void builderSeat() {
bike.setSeat("真皮");
}
@Override
public Bike createBike() {
return bike;
}
}
public class OfoBuilder extends Builder{
@Override
public void builderFrame() {
bike.setFrame("铝合金");
}
@Override
public void builderSeat() {
bike.setSeat("橡胶车座");
}
@Override
public Bike createBike() {
return bike;
}
}
** 指挥者类**
//指挥者类
public class Director {
private Builder builder;
public Director() {
}
public Director(Builder builder) {
this.builder = builder;
}
public void setBuilder(Builder builder) {
this.builder = builder;
}
//组装自行车
public Bike construct(){
builder.builderFrame();
builder.builderSeat();
return builder.createBike();
}
}
客户端
public class Client {
public static void main(String[] args) {
Director director = new Director();
director.setBuilder(new MobileBuilder());
Bike bike = director.construct();
System.out.println(bike.getFrame());
System.out.println(bike.getSeat());
}
}
模式扩展
public class Phone {
private String cpu;
private String screen;
private String memory;
private String mainboard;
public static final class Builder{
private String cpu;
private String screen;
private String memory;
private String mainboard;
public Builder cpu(String cpu){
this.cpu = cpu;
return this;
}
public Builder screen(String screen){
this.screen = screen;
return this;
}
public Builder memory(String memory){
this.memory = memory;
return this;
}
public Builder mainboard(String mainboard){
this.mainboard = mainboard;
return this;
}
public Phone build(){
return new Phone(this);
}
}
public Phone() {
}
private Phone(Builder builder){
this.cpu = builder.cpu;
this.screen = builder.screen;
this.memory = builder.memory;
this.mainboard = builder.mainboard;
}
public Phone(String cpu, String screen, String memory, String mainboard) {
this.cpu = cpu;
this.screen = screen;
this.memory = memory;
this.mainboard = mainboard;
}
public String getCpu() {
return cpu;
}
public void setCpu(String cpu) {
this.cpu = cpu;
}
public String getScreen() {
return screen;
}
public void setScreen(String screen) {
this.screen = screen;
}
public String getMemory() {
return memory;
}
public void setMemory(String memory) {
this.memory = memory;
}
public String getMainboard() {
return mainboard;
}
public void setMainboard(String mainboard) {
this.mainboard = mainboard;
}
@Override
public String toString() {
return "Phone{" +
"cpu='" + cpu + '\'' +
", screen='" + screen + '\'' +
", memory='" + memory + '\'' +
", mainboard='" + mainboard + '\'' +
'}';
}
}
客户端
public class Client {
public static void main(String[] args) {
Phone phone = new Phone.Builder()
.cpu("intel")
.screen("三星")
.memory("金士顿")
.mainboard("华硕")
.build();
System.out.println("链接编程风格====="+phone);
Phone phone1 = new Phone("intel", "三星", "金士顿", "华硕");
System.out.println("常规赋值风格====="+phone1);
}
}