-
概念:确保一个类在程序全局中只有一个实例,并只提供了一个全局的唯一访问点。最典型的就是Logger的创建。因为仅仅需要一个logger就可以满足全局的使用。
-
使用一个私有无参构造函数
private Signleton(){}保证不能通过构造函数进行单例对象的实例化。 -
使用一个私有变量
private Signleton uniqueInstance;(一般是静态的)来保证这个单例只有一个对象能够进行访问 -
使用一个公有的访问点
public Signleton getInstance(){}来对该单例中的唯一私有变量进行访问 -
懒汉式:线程不安全,在第一次调用get方法时才对对象进行实例化(即new一个单例到达私有变量中),但若多个线程同时到达get方法中,则可能同时new多个单例对象
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}- 饿汉式:线程安全,在一开始直接将单例变量进行实例化,不会进入if判断,也不会new,但是若该单例一直未被使用,则十分消耗资源。
- 懒汉式-线程安全:为get方法加上synchronized修饰,一次只有一个方法能够进入并获取实例,虽然线程安全,但是效率偏低
- 双重校检锁:对get方法中的是否实例化进行对次判断并添加synchronized进行修饰,为实例变量添加volatile进行轻量级锁修饰,防止在多线程下呗jvm进行指令重排,即先分配内存空间,在初始化对象,则中间调用时会调用到有地址为初始化的对象实例
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {
}
public static Singleton getUniqueInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}- 静态内部类:将私有实例变量以
private static final Singleton INSTANCE = new Singleton();后放在单例中的一个静态内部类中,在调用get时,才会初始化静态内部类,再在类加载时对其中的静态变量进行初始化。静态变量的加载过程中,有jvm保证了线程安全的特性 - 枚举实现:在保证了线程安全和其他特性的基础上,枚举实现还可以防止单例被反射攻击,即使暴力反射也不能获得多个单例实例。枚举的构造函数天生别第一位
static final,其只会被实例化一次,故通过jvm就可以保证其单例的实现和线程安全,以及防止反射攻击的可能
class Test{
SomeThing.INSTANCE.getIntance(); //获得枚举类中的唯一实例
}
public enum SomeThing {
INSTANCE;
private Test instance;
SomeThing {
instance = new Test;
}
public Test getInstance() {
return instance;
}
}//枚举类自身实现了序列化接口,能够有利于序列化操作
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable- 概念:在创建一个对象时不向创建者暴露细节,而是调用工厂来进行实例化并返回。
- 该工厂下的所有需要创建的对象都使用了一个公用接口,以便调用时能够使用向下转型
- 在工厂类中使用构造函数重载的形式来对需要返回的类型进行判断
//定义一个公共接口,工厂中的所有类都继承这个接口
public interface PublicClass{}
public class implement1 implements PublicClass{}
public class implement2 implements PublicClass{}
public class implement3 implements PublicClass{}
public class SimpleFactory{
public PublicClass creatClass(int x) {
if(x == 1) {
return new implement1();//调用create方法时就将对象new出去,以便接收使用
} else if(x == 2) {
return new implement2();
}
//.......
}
}
public class Client{
public static void main(String[] args) {
SimpleFactory sf = new SimpleFactory();
PublicClass pc1 = sf.creatClass(1);//直接通过接口来创建一个具体的类对象,类似集合的创建
}
}- 概念:在使用了接口之后,使用一个抽象类来进行工厂的简易实现,每一个实现类都添加一个实现工厂基础抽象类的工厂。一次只会返回一个相关的接口类
public abstract class Factory{
public abstract PublicClass factoryMethod();//用于创建该接口不同实现类的不同工厂实现
public void doSomeThing() {
PublicClass pc = factoryMethod();
//一些接口相关的公有事项方法
}
}
public class ConcreteFactory1 extends Factory{
public PublicClass factoryMethod(){ //实现工厂中的抽象方法,并返回特定的接口实类
return class1;
}
}- 概念:和工厂类似,也提供共有接口,但是返回一个对象家族,即多个相关联的对象
- 通过多个父接口描述一个具体对象,对接口进行实现,每个接口的实现有多个
- 将多个工厂放入到抽象工厂中,调用抽象工厂返回具体工厂,工厂继承抽象工厂来对具体需要返回的对象进行查找并返回
- 再通过调用工厂得到返回的对象并使用
//抽象工厂
public abstract class AbstractFactory {
abstract AbstractProductA createProductA();
abstract AbstractProductB createProductB();
}
//工厂的具体实现,继承自抽象工厂
public class ConcreteFactory1 extends AbstractFactory {
AbstractProductA createProductA() {//返回的具体类由其接口来接收,
return new ProductA1();
}
AbstractProductB createProductB() {
return new ProductB1();
}
}-
产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
-
抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
-
具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
-
指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
-
相同的方法,不同的执行顺序,产生不同的结果
-
多个部分或零件,都可以装配到一个对象中,但是产生的结果是不一样的
-
产品类十分的复杂,或者产品类中不同的调用顺序产生不同的结果
-
初始化一个对象非常复杂,参数多,而且很多参数都有默认值
(1) 产品角色:包含多个组成部件的复杂对象。
class Product {
private String partA;
private String partB;
private String partC;
public void setPartA(String partA) {
this.partA = partA;
}
public void setPartB(String partB) {
this.partB = partB;
}
public void setPartC(String partC) {
this.partC = partC;
}
public void show() {
//显示产品的特性
}
}(2) 抽象建造者:包含创建产品各个子部件的抽象方法。
abstract class Builder { //创建产品对象
protected Product product = new Product();
public abstract void buildPartA();
public abstract void buildPartB();
public abstract void buildPartC();
//返回产品对象
public Product getResult() {
return product;
}}(3) 具体建造者:实现了抽象建造者接口。
public class ConcreteBuilder extends Builder {
public void buildPartA() {
product.setPartA("建造 PartA");
}
public void buildPartB() {
product.setPartB("建造 PartB");
}
public void buildPartC() {
product.setPartC("建造 PartC");
}
}(4) 指挥者:调用建造者中的方法完成复杂对象的创建。
class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
} //产品构建与组装方法
public Product construct() {
builder.buildPartA();
builder.buildPartB();
builder.buildPartC();
return builder.getResult();
}
}(5) 客户类。
public class Client {
public static void main(String[] args) {
Builder builder = new ConcreteBuilder();
Director director = new Director(builder);
Product product = director.construct();
product.show();
}
}-
通过复制将一个对象实例clone()为另一个对象实例,能够在一定程度上减少资源的消耗
-
java中可以直接通过实现Cloneable接口来使用clone()方法直接实现对象的复制,java中提供的clone方法时浅拷贝的实现
-
也即是在对象内部实现clone方法,能够用于保存类的实时信息,用于快照存储等用途
-
缺点也很明显,一般用的很少?