创建型
关注点是’怎样创建对象’,主要是将对象的创建与使用分离,降低系统的耦合度,使用户不需要关注对象的创建细节。
单列模式
概述
在全局范围下,一个类只存在一个实例对象
优缺点
优点:
- 保存内存中只有一个实例,减少内存开销
- 可以避免对资源的多重占用
- 可设置全局访问点,可以优化和共享资源的访问
缺点:
- 非面向抽象编程,扩展性低
- 并发测试中不利于调试
实现
- 饿汉式单列
/**
* 单列对象
*/
public class Singleton{
private static final Singleton singleton = new Singleton();
private String name;
private Integer age;
//此处省略get\set方法
//私有化构造方法
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
- 懒汉式单例
public class Singleton{
//使用volatile保证线程的可见性
private static volatile Singleton singleton = null;
private String name;
private Integer age;
//此处省略get\set方法
//私有化构造方法
private Singleton(){}
public static Singleton getInstance(){
//使用双重检查,防止实例重复创建
if(singleton == null){
synchronized (Singleton.class){
if(singleton = null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
原型模式
概述
用一个已创建的实例作为原型,通过复制该实例对象生成一个新对象,且该新对象具有与原型对象相同的数据内容
优缺点
优点:
- java自带的原型模式是基于内存二进制流的复制,相对直接new一个新对象性能更好
- 由于新对象基于原型对象,与原型对象具有相同的数据,可以在需要的时候恢复到初始值
- 简化了创建对象并设置初始值的过程
缺点:
- 需要为每个类都新增一个clone方法
- 每次改造类后都需要修改原有代码,降低了扩展性
- 当对象内组合了其他复杂对象且要实现深克隆时,需要编写更为复杂的代码
注:
浅克隆:创建新对象是,新对象和原型对象数据完全相同,对于引用数据类型的内存地址与原型对象一样
深克隆:创建新对象是,新对象和原型对象的基本数据类型完全相同,但引用对象也会被克隆,引用数据类型的内存地址不指向原有对象地址
实现
- 浅克隆
import java.util.Arrays;
/**
* 原型类,要克隆需要实现Cloneable接口
*/
public class Prototype implements Cloneable {
private List<String> hobby;
public void setHobby(List<String> hobby) {this.hobby = hobby;}
public List<String> getHobby() {return hobby;}
public Prototype() {}
public Object clone() throws CloneNotSupportedException {
return (Prototype) super.clone();
}
public static void main(String[] args) throws CloneNotSupportedException {
//创建原型对象
Prototype prototype = new Prototype();
prototype.setHobby(Arrays.asList("篮球", "读书", "看美女"));
//基于原型对象创建新对象
Prototype clone = (Prototype) prototype.clone();
System.out.println("prototype == clone:"+(prototype == clone));//false
System.out.println("prototype.hobby == clone.hobby:"+(prototype.getHobby() == clone.getHobby()));//true
}
}
- 深克隆
import java.util.ArrayList;
import java.util.Arrays;
/**
* 原型类,要克隆需要实现Cloneable接口
*/
public class Prototype implements Cloneable {
private List<String> hobby;
public void setHobby(List<String> hobby) {this.hobby = hobby;}
public List<String> getHobby() {return hobby;}
public Prototype() {}
public Object clone() throws CloneNotSupportedException {
Prototype clone = (Prototype) super.clone();
//新建一个对象再重新赋值给克隆对象
List<String> newHobby = new ArrayList<>();
newHobby.addAll(clone.getHobby());
clone.setHobby(newHobby);
return clone;
}
public static void main(String[] args) {
//创建原型对象
Prototype prototype = new Prototype();
prototype.setHobby(Arrays.asList("篮球", "读书", "看美女"));
//基于原型对象创建新对象
Prototype clone = (Prototype) prototype.clone();
System.out.println("prototype == clone:" + (prototype == clone));//false
System.out.println("prototype.hobby == clone.hobby:"+(prototype.getHobby() == clone.getHobby()));//false
}
}
工厂方法模式
概述
定义一个用于创建产品的接口,由子类决定生产什么产品。
优缺点
优点:
- 降低了系统框架的耦合程度
- 提高了系统的可扩展性
缺点:
- 增加了系统的复杂度和类的个数
- 工厂只能生产一种产品。可以通过抽象工厂模式解决
实现
/**
* 抽象产品
*/
public interface Fruit {
void show();
}
/**
* 具体产品
*/
public class Apple implements Fruit{
@Override
public void show() {
System.out.println("这是苹果");
}
}
public class Banana implements Fruit{
@Override
public void show() {
System.out.println("这是香蕉");
}
}
/**
* 抽象工厂:
* 提供了厂品的生成方法
*/
public interface AbstractFactory {
/**
* 抽象方法,子类工厂可重写此方法创建产品
* @return
*/
Fruit newProduct();
}
/**
* 具体工厂,用来生产Apple
*/
public class AppleFactory implements AbstractFactory{
@Override
public Fruit newProduct() {
return new Apple();
}
}
/**
* 具体工厂,用来生产Banana
*/
public class BananaFactory implements AbstractFactory{
@Override
public Fruit newProduct() {
return new Banana();
}
}
抽象工厂模式
概述
与工厂方法模式相差不大,只是一个工厂存在多个方法,能创建出配套的一系列产品
建造者模式
概述
将一个复杂对象的创建于表示分离,使同样的构建过程可以创建不同的部分
优缺点
优点:
- 封装性好,构建和表示分离
- 扩展性好,各个具体的构建相互独立,降低了系统的耦合度
- 将构建过程细化
缺点:
- 由于组成部分必须相同导致使用范围有限
- 不符合开闭原则,内部代码修改,建造者也得修改
实现
/**
* 具体产品:人类
*/
public class Human {
private String header;
private String hands;
private String foot;
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getHands() {
return hands;
}
public void setHands(String hands) {
this.hands = hands;
}
public String getFoot() {
return foot;
}
public void setFoot(String foot) {
this.foot = foot;
}
@Override
public String toString() {
return "Human{" +
"header='" + header + '\'' +
", hands='" + hands + '\'' +
", foot='" + foot + '\'' +
'}';
}
}
/**
* 人类抽象建造者
*/
public interface HumanBuilder {
/**
* 构建头部
*/
void builderHeader();
/**
* 构建手部
*/
void builderHands();
/**
* 构建足部
*/
void builderFoot();
/**
* 返回结果
* @return
*/
Human getResult();
}
/**
* 黑人具体建造者
*/
public class BlackHumanBuilder implements HumanBuilder{
private Human human;
public BlackHumanBuilder(){
human = new Human();
}
@Override
public void builderHeader() {
human.setHeader("黑人头部构建成功");
}
@Override
public void builderHands() {
human.setHands("黑人手部构建成功");
}
@Override
public void builderFoot() {
human.setFoot("黑人足部构建成功");
}
@Override
public Human getResult() {
return human;
}
}
/**
* 白人具体建造者
*/
public class WhiteHumanBuilder implements HumanBuilder{
private Human human;
public WhiteHumanBuilder(){
human = new Human();
}
@Override
public void builderHeader() {
human.setHeader("白人头部构建成功");
}
@Override
public void builderHands() {
human.setHands("白人手部构建成功");
}
@Override
public void builderFoot() {
human.setFoot("白人足部构建成功");
}
@Override
public Human getResult() {
return human;
}
}
/**
* 指挥者对象
*/
public class Director {
private HumanBuilder builder;
private Director(HumanBuilder builder){
this.builder = builder;
}
/**
* 产品构建
* @return
*/
public Human construct(){
builder.builderHeader();
builder.builderHands();
builder.builderFoot();
return builder.getResult();
}
public static void main(String[] args) {
WhiteHumanBuilder whiteHumanBuilder = new WhiteHumanBuilder();
Director director = new Director(whiteHumanBuilder);
Human human = director.construct();
System.out.println(human);
}
}