设计模式-工厂和单例模式
概念和作用

分类

7大原则

工厂模式
概念
工厂模式是创建型模式,它是对象创建的最佳方案,特别是创建对象过程比较复杂。(如果理解new对象就可以完成功能,不需要用工厂模式)。
好处
实现对象的创建和使用的解耦。
分类
简单工厂模式简单工厂模式
简介
也叫静态工厂模式,可以根据不参数创建不同的对象,被创建的对象都要有相同接口或者父类。
实战
需求
假如AAA是一个工厂,课程看成产品,使用AAA工厂创建不同的课程!
代码
接口及实现类
package com.aaa.dp.factory.simple;
/**
* @FileName: SoftwareTechnology
* @Description: 软件技术接口
* @Author: zhz
* @CreateTime: 2024/11/27 10:49
* @Version: 1.0.0
*/
public interface SoftwareTechnology {
/**
* 学习课程的方法
*/
void studyST();
}
package com.aaa.dp.factory.simple;
/**
* @FileName: JavaDev
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 10:51
* @Version: 1.0.0
*/
public class JavaDev implements SoftwareTechnology{
@Override
public void studyST() {
System.out.println("头悬梁,锥刺股努力学习java开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
package com.aaa.dp.factory.simple;
/**
* @FileName: PythonDev
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 10:54
* @Version: 1.0.0
*/
public class PythonDev implements SoftwareTechnology{
@Override
public void studyST() {
System.out.println("头悬梁,锥刺股努力学习Python开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
工厂类
package com.aaa.dp.factory.simple;
/**
* @FileName: AAAFactory
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 10:55
* @Version: 1.0.0
*/
public class AAAFactory {
/**
* 教授课程的方法
* @param type
* @return
*/
public static SoftwareTechnology teachST(int type){
//判断 参数不同 返回值不同
if(type==1){
return new JavaDev();
} else if (type==2) {
return new CDev();
} else if (type==3) {
return new PythonDev();
}else {
return null;
}
}
}
测试
package com.aaa.dp.factory.simple;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 10:58
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
SoftwareTechnology softwareTechnology = AAAFactory.teachST(5);
if(softwareTechnology!=null){
softwareTechnology.studyST();
}else {
System.out.println("参数输入错误!");
}
}
}
缺点
1,违反开闭原则(增加新课程就需要修改工厂类)
2,代码耦合度高(任意一个课程出问题,可能影响其他课程的创建)
工厂方法模式
简介
为了解决简单工厂模式中存在的问题,定义一个工厂规范,生产产品不再是工厂完成,而是交给工厂的子类来完成,新增产品通过开分厂方式完成。可以降低产品之间的耦合度,完美遵循开闭原则。
实战
需求
假如AAA规模扩大,要添加新的课程,使用开分校的方式来增加课程!
代码
工厂标准
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: AAAStanderd
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:24
* @Version: 1.0.0
*/
public interface AAAStandered {
/**
* 教授软件类课程
* @return
*/
SoftwareTechnology testST();
}
新产品
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: DotNetDev
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:27
* @Version: 1.0.0
*/
public class DotNetDev implements SoftwareTechnology {
@Override
public void studyST() {
System.out.println("头悬梁,锥刺股努力学习.net开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: UIDev
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:21
* @Version: 1.0.0
*/
public class UIDev implements SoftwareTechnology {
@Override
public void studyST() {
System.out.println("头悬梁,锥刺股努力学习UI开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
分厂代码
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.AAAFactory;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: WuHanAAAFactory
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:26
* @Version: 1.0.0
*/
public class WuHanAAAFactory implements AAAStandered {
@Override
public SoftwareTechnology testST() {
return new UIDev();
}
}
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: BeijingAAAFactory
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:27
* @Version: 1.0.0
*/
public class BeijingAAAFactory implements AAAStandered {
@Override
public SoftwareTechnology testST() {
return new DotNetDev();
}
}
测试
package com.aaa.dp.factory.method;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:29
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
AAAStandered wuHanAAAFactory =new WuHanAAAFactory();
SoftwareTechnology softwareTechnology = wuHanAAAFactory.testST();
softwareTechnology.studyST();
AAAStandered beijingAAAFactory =new BeijingAAAFactory();
SoftwareTechnology softwareTechnology1 = beijingAAAFactory.testST();
softwareTechnology1.studyST();
}
}
缺点
代码复杂度变高
抽象工厂模式
简介
抽象工厂模式是方法工厂模式的增强版,在工厂方法模式中,只能提供生产一系列产品,而抽象工厂可以生产多个系列的产品。让不相关的产品系列拥有共同的父类或者接口,方便使用多态。
实战
需求
AAA规模不断扩大,不只在软件领域做培训,还在挖掘机领域做培训。。。
代码
抽象接口
package com.aaa.dp.factory.abstract1;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: AAAAbstractStandard
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:54
* @Version: 1.0.0
*/
public interface AAAAbstractStandard {
/**
* 教授软件类课程
* @return
*/
SoftwareTechnology testST();
/**
* 教授挖掘机类课程
* @return
*/
DiggerTechnology testDT();
//更多系列,可以再教授 美发 烹饪 汽修。。。
}
工厂类
package com.aaa.dp.factory.abstract1;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: ShenzhenAAAFactory
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:55
* @Version: 1.0.0
*/
public class ShenzhenAAAFactory implements AAAAbstractStandard{
@Override
public SoftwareTechnology testST() {
return new BigDataDev();
}
@Override
public DiggerTechnology testDT() {
return new SmallDiggerOpt();
}
}
新增产品接口
package com.aaa.dp.factory.abstract1;
/**
* @FileName: DiggerTechnology
* @Description: 挖掘机技术接口
* @Author: zhz
* @CreateTime: 2024/11/27 11:50
* @Version: 1.0.0
*/
public interface DiggerTechnology {
/**
* 学习挖掘机课程的方法
*/
void studyDT();
}
产品实现类
package com.aaa.dp.factory.abstract1;
/**
* @FileName: SmallDiggerOpt
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:52
* @Version: 1.0.0
*/
public class SmallDiggerOpt implements DiggerTechnology{
@Override
public void studyDT() {
System.out.println("头悬梁,锥刺股努力学习小型挖掘机开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
package com.aaa.dp.factory.abstract1;
/**
* @FileName: SmallDiggerOpt
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:52
* @Version: 1.0.0
*/
public class MediumDiggerOpt implements DiggerTechnology{
@Override
public void studyDT() {
System.out.println("头悬梁,锥刺股努力学习中型挖掘机开发技术,高薪就业,将来当上CTO,迎娶白富美/高富帅......走上人生巅峰!");
}
}
测试类
package com.aaa.dp.factory.abstract1;
import com.aaa.dp.factory.simple.SoftwareTechnology;
/**
* @FileName: Test
* @Description:
* @Author: zhz
* @CreateTime: 2024/11/27 11:58
* @Version: 1.0.0
*/
public class Test {
public static void main(String[] args) {
ShenzhenAAAFactory shenzhenAAAFactory =new ShenzhenAAAFactory();
SoftwareTechnology softwareTechnology = shenzhenAAAFactory.testST();
softwareTechnology.studyST();
DiggerTechnology diggerTechnology = shenzhenAAAFactory.testDT();
diggerTechnology.studyDT();
}
}
缺点
1,违反开闭原则(增加更多系列培训时,修改抽象接口)
2,耦合度高(多系列产品,相互影响)
单例模式
概念
单例模式是创建型模式之一,是一种常见的设计模式。就是在项目运行过程中一个类只存在一个对象,无论多少地方调用。
好处
节省内存
实现要点
1,私有构造(保证该类在其他地方无法实例化对象)
2,私有静态属性(私有,不能在其他地方调用。静态,伴随类加载执行,并且就执行一次)
3,公共的静态的返回当前实例方法
实现方式
懒汉非线程安全模式
package com.aaa.dp.singleton;
/**
* @FileName: SingletonA
* @Description: 懒汉非线程安全模式
* @Author: zhz
* @CreateTime: 2024/11/27 16:03
* @Version: 1.0.0
*/
public class SingletonA {
/**
* 1,私有构造函数 (保证该类在其他地方无法实例化对象)
*/
private SingletonA(){
}
//2,私有静态本类属性
//私有:不能在其他地方调用。 静态: 伴随类加载执行,并且就执行一次
private static SingletonA singletonA = null;
/**
* 3,公共(其他地方可以调用)静态(通过类名称能调用)方法
* @return
*/
public static SingletonA getInstance(){
//判断为null 再实例化对象
if(singletonA==null){
singletonA = new SingletonA();
}
return singletonA;
}
}
懒汉线程安全模式
package com.aaa.dp.singleton;
/**
* @FileName: SingletonA
* @Description: 懒汉线程安全模式
* @Author: zhz
* @CreateTime: 2024/11/27 16:03
* @Version: 1.0.0
*/
public class SingletonB {
/**
* 1,私有构造函数 (保证该类在其他地方无法实例化对象)
*/
private SingletonB(){
}
//2,私有静态本类属性
//私有:不能在其他地方调用。 静态: 伴随类加载执行,并且就执行一次
private static SingletonB singletonB = null;
/**
* 3,公共(其他地方可以调用)静态(通过类名称能调用)方法
* @return
*/
public static synchronized SingletonB getInstance(){
//判断为null 再实例化对象
if(singletonB==null){
singletonB = new SingletonB();
}
return singletonB;
}
}
懒汉双检锁模式
package com.aaa.dp.singleton;
/**
* @FileName: SingletonA
* @Description: 懒汉双检锁模式
* @Author: zhz
* @CreateTime: 2024/11/27 16:03
* @Version: 1.0.0
*/
public class SingletonC {
/**
* 1,私有构造函数 (保证该类在其他地方无法实例化对象)
*/
private SingletonC(){
}
//2,私有静态本类属性
//私有:不能在其他地方调用。 静态: 伴随类加载执行,并且就执行一次
/***
* volatile 不稳定的,短暂的 java关键字
* 1,多线程可见 (参考VolatileDemo类)volatile修改某一个属性时,一个线程如果更改了属性的值,另一个线程立马可见
* 2,防止指令重排
*
* 在计算机底层,为了加快速度,在不影响程序执行结果的情况下,进行执行重排
* int i=1;
* int j=2;
* volatile int d=4; a b 赋值一定在 i j之后执行
* int a=3;
* int b=4;
* int k=i+j;
* int c=a+b;
* SingletonC singletonC = new SingletonC()
* jvm分为三个步骤(不是原子性):
* 1,先在堆开辟空间
* 2,调用构造进行实例化
* 3,拿引用singletonC指向开辟的空间
* 执行顺序 不加volatile 可能 1 ->3 ->2 ...
* 加volatile 必然是1 2 3
*
*/
private static volatile SingletonC singletonC = null;
/**
* 3,公共(其他地方可以调用)静态(通过类名称能调用)方法
* @return
*/
public static SingletonC getInstance(){
//判断为null 再实例化对象
if(singletonC==null){
//使用代码块加锁
synchronized (SingletonC.class) {
//再次判断
if(singletonC==null) {
singletonC = new SingletonC();
}
}
}
return singletonC;
}
}
饿汉线程安全模式
package com.aaa.dp.singleton;
/**
* @FileName: SingletonA
* @Description: 饿汉线程安全
* @Author: zhz
* @CreateTime: 2024/11/27 16:03
* @Version: 1.0.0
*/
public class SingletonD {
/**
* 1,私有构造函数 (保证该类在其他地方无法实例化对象)
*/
private SingletonD(){
}
//2,私有静态本类属性
private static final SingletonD SINGLETON_D =
new SingletonD();
/**
* 3,公共(其他地方可以调用)静态(通过类名称能调用)方法
* @return
*/
public static SingletonD getInstance(){
return SINGLETON_D;
}
}
饿汉静态块模式
package com.aaa.dp.singleton;
/**
* @FileName: SingletonA
* @Description: 饿汉静态块线程安全
* @Author: zhz
* @CreateTime: 2024/11/27 16:03
* @Version: 1.0.0
*/
public class SingletonE {
/**
* 1,私有构造函数 (保证该类在其他地方无法实例化对象)
*/
private SingletonE(){
}
//2,私有静态本类属性
private static SingletonE SINGLETON_E = null;
//静态匿名块
static {
//如果当前类创建不是一行代码,需要多行代码,使用该方式
//参考mybatis第一章课程 SqlSessionFactory创建过程
SINGLETON_E=new SingletonE();
}
/**
* 3,公共(其他地方可以调用)静态(通过类名称能调用)方法
* @return
*/
public static SingletonE getInstance(){
return SINGLETON_E;
}
}
懒汉和饿汉区别?
1,类加载速度:懒汉快(类加载时不实例化对象),饿汉慢
2,获取对象速度:懒汉慢(获取时需要实例化对象),饿汉快
3,生命周期:从早上8点启动tomcat到晚上8点停止tomcat,饿汉只要启动,就被实例化,生命周期就开始了。。从早8到晚8,饿汉什么时候调用,什么时候声明周期才开始。。。假如12调用,生命周期就是12点到晚8点。。。
volatile关键用法
volatile 不稳定的,短暂的 java关键字
1,多线程可见 (参考VolatileDemo类)volatile修改某一个属性时,一个线程如果更改了属性的值,另一个线程立马可见
2,防止指令重排
- 在计算机底层,为了加快速度,在不影响程序执行结果的情况下,进行执行重排
- int i=1;
- int j=2;
- volatile int d=4; a b 赋值一定在 i j之后执行
- int a=3;
- int b=4;
- int k=i+j;
- int c=a+b;
- SingletonC singletonC = new SingletonC()
- jvm分为三个步骤(不是原子性):
- 1,先在堆开辟空间
- 2,调用构造进行实例化
- 3,拿引用singletonC指向开辟的空间
- 执行顺序 不加volatile 可能 1 ->3 ->2 ...
- 加volatile 必然是1 2 3
多线程可见实例
package com.aaa.dp.singleton;
/**
* @FileName: VolatileDemo
* @Description: Volatile 多线程可见的用法
* @Author: zhz
* @CreateTime: 2024/11/27 16:33
* @Version: 1.0.0
*/
public class VolatileDemo extends Thread{
private static volatile boolean flag = true;
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+",开始运行-----");
//死循环,不会停止
while (flag);
}
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName()+",开始运行-----");
new VolatileDemo().start();
//main线程休眠5秒
Thread.sleep(5000);
System.out.println("5秒后让flag值变化");
flag=false;
System.out.println(Thread.currentThread().getName()+",结束运行-----");
//不加 volatile main线程把flag的值改为false thread-0看不到它改了
//加 volatile main线程把flag的值改为false thread-0直接看到它改了
}
}
浙公网安备 33010602011771号