单例模式
1… 饥饿模式
package singleton;
/**
*
* @author 荞荞 饥饿模式
*/
public class SingletonDemo01 {
//一个私有构造函数
private SingletonDemo01() {
};
//生成一个实例
private static SingletonDemo01 instance = new SingletonDemo01();
//静态方法,获得实例对象
private static SingletonDemo01 getInstance() {
return instance;
}
public String hello(String name) {
return "hello" + name;
}
/*
* 测试多线程下单例模式是否安全
*
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(SingletonDemo01.getInstance().hashCode());
}).start();
}
}
}
这种模式简单安全
2… 懒汉式, 有线程问题
package singleton;
/**
* 单例模式: 懒汉式, 有线程问题
*/
public class SingletonDemo02 {
private SingletonDemo02(){
//模拟构造函数的运行耗时
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static SingletonDemo02 singletonDemo02 = null;
public static synchronized SingletonDemo02 getInstance() {
if (singletonDemo02 == null) {
singletonDemo02 = new SingletonDemo02();
}
return singletonDemo02;
}
public String hello(String name) {
return "hello " + name;
}
/*
* 测试多线程下单例模式是否安全
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(SingletonDemo02.getInstance().hashCode());
}).start();
}
}
}
就和上面说的一样,在安全上存在一定的线程问题,并发量一高,容易崩。
3… 懒汉式,线程安全,但性能较低
双重检查
package singleton;
/**
* 单例模式: 懒汉式,线程安全,但性能较低
*/
public class SingletonDemo03 {
private SingletonDemo03() {
//模拟构造函数的运行耗时
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static SingletonDemo03 singletonDemo03 = null;
public static SingletonDemo03 getInstance(){
//系统减小同步块来提升性能,可以吗?
if(singletonDemo03 == null) {
///....
synchronized (SingletonDemo03.class) {
if(singletonDemo03 == null) {
singletonDemo03 = new SingletonDemo03();
}
}
}
return singletonDemo03;
}
public String hello(String name) {
return "hello " + name;
}
/*
* 测试多线程下单例模式是否安全
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(SingletonDemo03.getInstance().hashCode());
}).start();
}
}
}
这种单例模式,重点在于俩次if判断,特别是第二次if判断,因为如果不写这次判断,那么就会出现线程问题,当然是可能,那为什么会出现这问题呢,就是由于CPU只有一个,在极小的时间内,CPU可能去服务其他线程,那这次就会被抢掉,是不是就会出现重新实例对象,不过在经过第一次判断后,通过同步锁,在进行一次判断,就可以实现单例模式,也不会出现线程被抢的问题,就是安全的
4… 懒加载, 线程安全
package singleton;
/**
* 单例模式: 懒加载, 线程安全
*/
public class SingletonDemo04 {
//阻止外部实例化
private SingletonDemo04() {
//模拟构造函数运行耗时
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static {
}
//使用静态内部类来使用一个SingletonDemo04对象
private static class SingletonDemoHolder {
private final static SingletonDemo04 instance = new SingletonDemo04();
}
public static SingletonDemo04 getInstance() {
return SingletonDemoHolder.instance;
}
public String hello(String name) {
return "hello " + name;
}
/*
* 测试多线程下单例模式是否安全
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(SingletonDemo04.getInstance().hashCode());
}).start();
}
}
}
package innerclasstest;
import java.util.Random;
public class OuterClass {
public static long OUTER_DATE = System.currentTimeMillis();
public static int a = 1;
static {
System.out.println("外部类静态块加载时间:" + System.currentTimeMillis());
}
public OuterClass() {
timeElapsed();
System.out.println("外部类构造函数事件:" + System.currentTimeMillis());
}
static class InnerStaticClass {
static {
System.out.println("内部类静态块加载时间:" + System.currentTimeMillis());
}
// 类加载的初始化阶段是单线程的,类变量的赋值语句在编译生成字节码的时候写在函数中,初始化时单线程调用这个完成类变量的赋值,
// 所以此处可以保存线程安全的
public static double INNER_DATE = System.currentTimeMillis();
}
class InnerClass {
public long INNER_DATE = 0;
public InnerClass() {
timeElapsed();
INNER_DATE = System.currentTimeMillis();
}
}
public static void Hello(){System.out.println("Hello");}
public static void main(String[] args) {
//System.out.println("外部类常量加载时间:" + OuterClass.OUTER_DATE);
//OuterClass.Hello();
//OuterClass outer = new OuterClass();
//System.out.println("外部类静态变量加载时间:" + OuterClass.OUTER_DATE);
//System.out.println("外部类静态变量加载时间:" + outer.OUTER_DATE);
System.out.println(InnerStaticClass.INNER_DATE);
}
//单纯的为了耗时而已
private void timeElapsed() {
for (int i = 0; i < 10000000; i++) {
int a = new Random(100).nextInt(), b = new Random(100).nextInt();
a = a + b;
}
}
}
5… enum型
package singleton;
public enum SingletonDemo05 {
INSTANCE;
public String hello(String name) {
return "hello " + name;
}
/*
* 测试多线程下单例模式是否安全
* @param args
*/
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(SingletonDemo05.INSTANCE.hashCode());
}).start();
}
}
}
简单工厂
用于产生对象的方法或者式类,称之为工厂。 上面所讲到的单例模式也可以看作为一个特殊的工厂。
为了使我们的设计模式变得更加的灵活,我们就通过工厂模式来实现来集中控制对象的创建过程,spring的IOC容器就是工厂模式的经典实现,用于生产指定系列的对象。已鸭子为例,鸭子有真的鸭子,橡皮鸭,电子玩具鸭等。如何能方便的创建出各种鸭子,并将创建过程控制起来,以便于以后的维护和扩展?
main
package simplefactory;
public class WildDuck extends Duck {
@Override
public void quack() {
System.out.println("我是曾烦鸭。。。。。。。。");
}
}
DonaldDuck
package simplefactory;
public class DonaldDuck extends Duck {
@Override
public void quack() {
System.out.println("我是唐老鸭");
}
}
rebberduck
package simplefactory;
public class RubberDuck extends Duck {
@Override
public void quack() {
System.out.println("我是橡皮鸭,");
}
}
wildDuck
package simplefactory;
public class WildDuck extends Duck {
@Override
public void quack() {
System.out.println("我是曾烦鸭。。。。。。。。");
}
}
DuckFactory
package simplefactory;
public class DuckFactory {
private DuckFactory(){}
private static DuckFactory duckFactory = new DuckFactory();
public static final int WILD_DUCK = 1;
public static final int RUBBER_DUCK = 2;
public static final int DONALD_DUCK = 3;
public static final int PJ_DUCK = 4;
public static Duck getInstance(int duckType) {
switch (duckType) {
case WILD_DUCK:
return new WildDuck();
case RUBBER_DUCK:
return new RubberDuck();
case DONALD_DUCK:
return new DonaldDuck();
case PJ_DUCK:
return new PJDuck();
default:
return null;
}
}
}
duck
package simplefactory;
public abstract class Duck {
abstract public void quack();
}
pjduck
package simplefactory;
/**
* @author L
* @site www.xiaomage.com
* @company xxx鍏徃
* @create聽 2022-06-20 11:12
*/
public class PJDuck extends Duck {
@Override
public void quack() {
System.out.println("我是嘎嘎嘎...");
}
}
总结:无论是单例模式还是简单工厂模式,在两种设计模式都是想让代码的耦合性降低,在拓展和以后的功能变更和需求增加的时候不至于说去改其他代码,减低bug的出现,使得代码的灵活性得到一个提高。