建造者模式
结构
- 抽象构建者
- 具体建造者
- 产品
- 指挥者
简单实现
例:角色扮演类游戏,不同人物在不同场景会有不同的能力,并且可以装扮不同的外表。
// 复杂产品对象
public class Actor {
private String type;
private String sex;
private String face;
private String costume;
private String hairstyle;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getFace() {
return face;
}
public void setFace(String face) {
this.face = face;
}
public String getCostume() {
return costume;
}
public void setCostume(String costume) {
this.costume = costume;
}
public String getHairstyle() {
return hairstyle;
}
public void setHairstyle(String hairstyle) {
this.hairstyle = hairstyle;
}
}
// 抽象建造者
public abstract class ActorBuilder {
protected Actor actor = new Actor();
public abstract void buildType();
public abstract void buildSex();
public abstract void buildFace();
public abstract void buildCostume();
public abstract void buildHairstyle();
// 工厂方法,返回一个完整的对象
public Actor createActor(){
return actor;
}
}
// 英雄角色建造者,具体建造者
public class HeroBuilder extends ActorBuilder {
@Override
public void buildType() {
actor.setType("英雄");
}
@Override
public void buildSex() {
actor.setSex("男");
}
@Override
public void buildFace() {
actor.setFace("英俊");
}
@Override
public void buildCostume() {
actor.setCostume("盔甲");
}
@Override
public void buildHairstyle() {
actor.setHairstyle("飘逸");
}
}
// 角色控制者
public class ActorController {
public Actor createrActor(ActorBuilder ab) {
Actor actor;
ab.buildType();
ab.buildSex();
ab.buildFace();
ab.buildCostume();
ab.buildHairstyle();
actor = ab.createActor();
return actor;
}
}
// 客户端调用
public class Client {
public static void main(String[] args) {
ActorBuilder ab;
ab = XmlBeans.getBean();// 通过配置文件获取
ActorController ac = new ActorController();
Actor actor = ac.createrActor(ab);
}
}
定义
建造者模式就是为了实现灵活的构建一个复杂对象,将对象和对象创建过程解耦,告诉指挥者我想要一个什么样的对象,指挥者去调用对应的具体构建者来创建对象。
原型模式
结构
- 抽象原型类
- 具体原型类
- 客户类
简单实现
例:周报的模板,提供给每一个员工使用,模板使用原型模式,每个员工可以下载附件模板写自己的周报。
// 模板类
public class Attachment implements Serializable {
private String name;// 附件名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void downLoad() {
System.out.println("下载附件,文件名为" + name);
}
}
//工作周报类 Cloneable是浅克隆,Serializale是深克隆
public class WeeklyLog implements Cloneable, Serializable {
private Attachment attachment;
private String name;
private String date;
private String content;
public Attachment getAttachment() {
return attachment;
}
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public WeeklyLog clone(){
Object obj = null;
try {
obj = super.clone();
return (WeeklyLog) obj;
} catch (CloneNotSupportedException e) {
System.out.println("不支持复制!");
return null;
}
}
// 深克隆
public WeeklyLog deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (WeeklyLog) ois.readObject();
}
}
// 客户端类
public class Client {
public static void main(String[] args) throws IOException, ClassNotFoundException {
WeeklyLog log_previous, log_new;
log_previous = new WeeklyLog();
Attachment attachment = new Attachment();
log_previous.setAttachment(attachment);
// 浅克隆
log_new = log_previous.clone();
// 比较周报
System.out.println("周报是否相同?" + (log_previous == log_new));
// 比较模板
System.out.println("模板是否相同?" + (log_previous.getAttachment() == log_new.getAttachment()));
// 深克隆
log_new = log_previous.deepClone();
// 比较周报
System.out.println("周报是否相同?" + (log_previous == log_new));
// 比较模板
System.out.println("模板是否相同?" + (log_previous.getAttachment() == log_new.getAttachment()));
}
}
周报是否相同?false
模板是否相同?true
周报是否相同?false
模板是否相同?false
定义
原型模式和单例模式相对应,原型模式就是复制出许多过和原对象一样的对象,但是地址不同,原型对象的复制又分为两种
- 浅克隆:复制对象本身和内部基本数据类型的成员变量,如果成员变量是引用类型则共用地址。
- 深克隆:复制对象和对象内所有的成员变量
Clone()方法和Cloneable接口:Clone方法是属于object,但是需要被克隆的类实现Cloneable,不然会抛出CloneNotSupportedException异常。Clone方法实现的就是浅克隆。深克隆可以用流的方法实现。
单例模式
单例模式从加载模式来分,分为饿汉式懒汉式
饿汉式
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
}
public static EagerSingleton getInstance() {
return instance;
}
}
懒汉式加载
public class LazySingleton {
private volatile static LazySingleton instance = null;
private LazySingleton() {
}
public static LazySingleton getInstance() {
// 第一重判断
if (instance == null) {
// 锁定代码块
synchronized (LazySingleton.class) {
// 第二重判断
if (instance == null) {
instance = new LazySingleton();// 创建单例实例
}
}
}
return instance;
}
}
内部类实现懒汉式延迟加载
public class Singleton {
private Singleton() {
}
// 静态内部类
private static class HolderClass {
private final static Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return HolderClass.instance;
}
}
枚举类
静态内部类通过反射和序列化可以破坏掉单例模式,枚举类由于java虚拟机的保护机制,确保枚举类对象只有一个,可以避免被反射或者序列化破坏单例。