目录
1 单例模式
需考虑的问题:
- 是否线程安全
- 是否延迟创建
- 有无破坏单例的方法
饿汉单例
public class _01Eager {
// 不延迟单例
// 类初始化时创建单例
private static final _01Eager instance = new _01Eager();
private _01Eager(){}
public static _01Eager getInstance(){
return instance;
}
}
懒汉单例
public class _02Lazyer {
// 方法延迟单例
// 相比于 饿汉式,把 instance 的创建
// 从 类初始化时 移动到 方法调用时
private static _02Lazyer instance;
private _02Lazyer(){}
public static synchronized _02Lazyer getInstance(){
if(instance == null)
instance = new _02Lazyer();
return instance;
}
}
双重检验单例
public class _03DoubleCheck {
// 方法延迟单例
// 相比 懒汉式,缩小锁粒度
private static _03DoubleCheck instance;
private _03DoubleCheck(){}
public static _03DoubleCheck getInstance(){
if(instance == null){
synchronized (_03DoubleCheck.class){
if(instance == null) {
instance = new _03DoubleCheck();
}
}
}
return instance;
}
}
静态内部类单例
public class _04Static implements Serializable {
private static class Static {
private final static _04Static instance = new _04Static();
}
private _04Static(){}
public static _04Static getInstance(){
return Static.instance;
}
}
破坏单例 (反射、反序列化)
(导入序列化工具依赖:org.apache.commons.commons-lang3
)
public class StaticAttack {
StaticAttack(){}
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 测试 反射和反序列化 破坏 静态内部类
staticAttack();
}
public static void staticAttack() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 单例对象
_04Static obj = _04Static.getInstance();
isSingleton(obj, _04Static.getInstance()); // true
// 测试是否可以破坏单例
_04Static newObj1, newObj2;
// 反射创建 新对象 可以破坏单例
Constructor<_04Static> constructor = _04Static.class.getDeclaredConstructor();
constructor.setAccessible(true);
newObj1 = constructor.newInstance();
isSingleton(obj, newObj1); // false
// 反序列化创建 新对象 可以破坏单例
byte[] serialize = SerializationUtils.serialize(obj);
newObj2 = SerializationUtils.deserialize(serialize);
isSingleton(obj, newObj2); // false
}
public static void isSingleton(Object obj1, Object obj2){
System.out.println("是否是单例? " + (obj1 == obj2));
}
}
枚举类单例
// 枚举类可以避免 反射 和 反序列化 破坏单例
public enum _05Enum {
SINGLETON;
// 单例的方法
public String doSomething(){
return "处理结束";
}
}
// 调用单例的方法
_05Enum.SINGLETON.doSomething();
2 工厂模式
简单工厂模式
- 消费者:依赖 商店
- 商店:依赖 工厂,返回 具体产品
- 工厂:if - else 地创建 具体产品
- 产品:产品种类 通过 实现 很多抽象产品(接口)
public class sf {
// 抽象产品类 Vehicle
interface Vehicle {}
// Vehicle 的 具体产品
static class Car implements Vehicle {
public String toString() {
return "Car";
}
}
static class Bike implements Vehicle {
public String toString() {
return "Bike";
}
}
// 所有具体产品 都共用 抽象产品的工厂
static class VehicleFactory {
Vehicle createVehicle(String type){
if(type == null)
return null;
Vehicle vehicle = null;
if(type.equalsIgnoreCase("Car"))
vehicle = new Car();
else if(type.equalsIgnoreCase("Bike"))
vehicle = new Bike();
return vehicle;
}
}
}
工厂方法模式
public class fm {
// 抽象产品类 Vehicle
interface Vehicle {}
// Vehicle 的 具体产品
static class Car implements Vehicle {
public String toString() {
return "Car";
}
}
static class Bike implements Vehicle {
public String toString() {
return "Bike";
}
}
// Vehicle 的 抽象工厂
static abstract class VehicleFactory {
abstract Vehicle createVehicle();
}
// *继承* 抽象工厂
// 一个具体产品 对应 一个具体工厂
static class CarFactory extends VehicleFactory {
Vehicle createVehicle(){
return new Car();
}
}
static class BikeFactory extends VehicleFactory {
Vehicle createVehicle() {
return new Bike();
}
}
}
3 抽象工厂模式
代码实现
public class af {
// 抽象工厂用于产品族
// 产品族 和 各自的抽象工厂
interface Vehicle {}
interface Accessory {}
// interface Engine {} 产品族拓展的例子
interface VehicleFactory {
Vehicle createVehicle();
}
interface AccessoryFactory {
Accessory createAccessory();
}
// interface EngineFactory { Engine createEngine();}
// Vehicle 的 具体产品
static class Car implements Vehicle {
public String toString() {
return "Car";
}
}
static class Bike implements Vehicle {
public String toString() {
return "Bike";
}
}
// Accessory 的具体产品
static class CarAccessory implements Accessory {
public String toString() {
return "CarAccessory";
}
}
static class BikeAccessory implements Accessory {
public String toString() {
return "BikeAccessory";
}
}
// 每 *实现* 一个接口,产品族就拓展一类产品
// 产品族工厂 实现了 多个接口,实现产品族的可拓展性
static class CarFactory implements
VehicleFactory, AccessoryFactory //,EngineFactory
{
public Vehicle createVehicle() {
return new Car();
}
public Accessory createAccessory() {
return new CarAccessory();
}
}
static class BikeFactory implements
VehicleFactory, AccessoryFactory //,EngineFactory
{
public Vehicle createVehicle() {
return new Bike();
}
public Accessory createAccessory() {
return new BikeAccessory();
}
}
}
对比三种工厂模式
| 简单工厂模式:
- A 产品:A1 - A2
简单工厂
/ if-else \
A1 A2
| 工厂方法模式:
- A 产品:A1 - A2
A 抽象工厂(抽象类)
- 生产 A
/ 继承 \
A1 具体工厂 A2 具体工厂
- 生产 A1 - 生产 A2
| 抽象工厂模式:
- (A, B, ...) 产品* 族 *:A1 - A2 | B1 - B2 | C ..
A 抽象工厂(接口) B 抽象工厂(接口) C 抽象工厂
- 生产 A (接口) - 生产 B (接口)
\ 多实现 /
(A1, B1) 具体产品族工厂
- 生产 A1 (实现接口)
- 生产 B1 (实现接口)
可以看到,抽象工厂可以实现最复杂的功能,但是在简单情形下增加了复杂性
如何选择工厂方法和抽象工厂?
在实际应用中,需要根据具体的需求和场景选择合适的模式:
- 如果产品种类较少,可以使用工厂方法模式
- 如果产品种类较多,形成了产品族(并且 产品族 有可能 增删 产品),可以使用抽象工厂模式