23中设计模式--创建型模式
• 抽象工厂模式(Abstract Factory Pattern)
这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。
在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
应用实例: 1、您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
2、Hibernate 换数据库只需换方言和驱动就可以。
• 抽象工厂模式(Abstract Factory Pattern)
是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
应用实例:工作了,为了参加一些聚会,肯定有两套或多套衣服吧,比如说有商务装(成套,一系列具体产品)、时尚装(成套,一系列具体产品),甚至对于一个家庭来说,可能有商务女装、商务男装、时尚女装、时尚男装,这些也都是成套的,即一系列具体产品。假设一种情况(现实中是不存在的,要不然,没法进入共产主义了,但有利于说明抽象工厂模式),在您的家中,某一个衣柜(具体工厂)只能存放某一种这样的衣服(成,。,套,一系列具体产品),每次拿这种成套的衣服时也自然要从这个衣柜中取出了。用 OOP 的思想去理解,所有的衣柜(具体工厂)都是衣柜类的(抽象工厂)某一个,而每一件成套的衣服又包括具体的上衣(某一具体产品),裤子(某一具体产品),这些具体的上衣其实也都是上衣(抽象产品),具体的裤子也都是裤子(另一个抽象产品)。
使用场景: 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。
注意事项:产品族难扩展,产品等级易扩展。
现代人,魔法人, 实现人接口的三个方法,具体实现工厂有这个三个方法的实现,具体实现工厂又继承了抽象工厂。
//main方法
//获取形状工厂 AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE"); //获取形状为 Circle 的对象 Shape shape1 = shapeFactory.getShape("CIRCLE"); //调用 Circle 的 draw 方法 shape1.draw(); //获取形状为 Rectangle 的对象 Shape shape2 = shapeFactory.getShape("RECTANGLE"); //调用 Rectangle 的 draw 方法 shape2.draw();
饿汉模式就够用了
//在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。静态变量只要加载到内存,就会初始化 public class SingletonObject1 { // 利用静态变量来存储唯一实例 private static final SingletonObject1 instance = new SingletonObject1(); // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){ return instance; } }
懒汉模式
// 用到了才加载,多线程的时候会出现线程不安全 public class SingletonObject1 { // 利用静态变量来存储唯一实例 private static SingletonObject1 instance ; // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){ if(instance ==null){ instance = new SingletonObject1(); } return instance ; } }
懒汉枷锁模式
// public class SingletonObject1 { // 利用静态变量来存储唯一实例 private static SingletonObject1 instance ; // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){ if(instance ==null){ synchronized (SingletonObject1.class){ if(instance ==null){ instance = new SingletonObject1(); } } } return instance ; } }
双重检查模式(减少锁的代码块)
// public class SingletonObject1 { // 利用静态变量来存储唯一实例 private static SingletonObject1 instance ; // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){ if(instance ==null){ synchronized (SingletonObject1.class){ if(instance ==null){ instance = new SingletonObject1(); } } } return instance ; } }
静态内部类实现懒加载模式
public class SingletonObject1 { // jvm保证单例,加载外部类时,不会加载内部类,保证懒加载 private static class SingletonObject{ private static final SingletonObject1 instance = new SingletonObject1(); } // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){ return SingletonObject.instance; } }
枚举实现,不仅解决线程同步,还能防止反序列化问题(枚举类没有构造方法)
public class SingletonObject1 { static enum SingletonEnum{ INSTANCE; private SingletonObject1 instance ; private SingletonEnum(){ instance = new SingletonObject1(); } public SingletonObject1 getInstance(){ return instance ; } } // 私有化构造函数 private SingletonObject1(){ // 里面可能有很多操作 } // 提供公开获取实例接口 public static SingletonObject1 getInstance(){
return SingletonEnum.INSTANCE.getInstance();
} }
枚举好处:
-
使用枚举实现
单例模式
更加简单!
线程安全:
-
枚举类最终会被编译为被
final
修饰的普通类 -
它的所有属性也都会被
static
和final
关键字修饰,所以枚举类在项目启动时就会被 JVM 加载并初始化且不允许更改!线程安全
方便比较:
-
枚举比较时使用 == 就够了,因为枚举类是在程序加载时就创建了(它并不是
new
出来的)每个对象全局只有一个!
-
== 比较地址,相同对象的地址也相同!
封装一个复杂对象的构建过程,并可以按步骤构造。
游戏中一个小的地形含有墙,水,草地等对象
通过建造者接口及建造者接口实现类,build().build().build()分步实现一个地形的创建。
Builder builder = new ConcreteBuilder(); //可通过配置文件实现 Director director = new Director(builder); Product product = director.construct();
克隆模式,实现接口Cloneable ,重写clone(),浅克隆和深克隆
浅克隆:克隆对象之间修改相互影响。