本篇博客主要是学习 韩顺平_Java设计模式 做一个学习笔记使用
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法)。 比如 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象。SessionFactory 并不是 轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,这是就会使用到单例模式。
1.1步骤
说明:
单例模式的实现由很多种写法, 其中主要有分类: 饿汉, 懒汉
在这里我就不写那些比较普通的, 或者线程不安全的写法了, 直接写出几种比较推荐的写法好了
1.2代码
/**
* 单例模式
* @author houyu
* @createTime 2019/11/8 9:40
*/
public class SingletonObject {
/** 私有构造 */
private SingletonObject() {}
/** -------------------- 方式1 (推荐 JVM 保证) -------------------- */
private static class SingletonHolder {
private static final SingletonObject instance = new SingletonObject();
}
public static SingletonObject getInstance() {
return SingletonHolder.instance;
}
/*
* 分析:
* 使用内部类的形式, 就算主类 (SingletonObject) 加载了, 内部类( SingletonHolder )也是使用到的时候再加载的, 由于使用了 private 修饰了, 其他类无法使用
*
* SingletonObject 导致类加载的原因有很多, 其中有一种可能就是被其他列 import 也会导致类的加载, 但是在不调用 getInstance 的使用, 都没有创建实例
*/
/** -------------------- 方式1 (推荐 JVM 保证) -------------------- */
/** -------------------- 方式2 (次推荐 饿汉形式 JVM 保证) -------------------- */
private static final SingletonObject instance = new SingletonObject();
public static SingletonObject getInstance2() {
return instance;
}
/*
* 分析:
* 使用静态常量的形式 也就是类一加载就创建实例, 一定程度上会导致内存的浪费(如果程序启动到结束都没有使用到改用的时候)
* 但是阅读jdk源码, 发现很多都是使用这个简单的形式创建的单例模式,因此 也是很受欢迎的
*/
/** -------------------- 方式3 (次推荐 synchronized volatile 锁机制保证, 双重检查) -------------------- */
private static volatile SingletonObject instance3;
public static SingletonObject getInstance3() {
if(instance3 == null) {
synchronized(Object.class) {
// if(instance3 == null) {
// instance3 = new SingletonObject();
// }
instance3 = instance3 == null ? new SingletonObject() : instance3;
}
}
return instance3;
}
/*
* 分析:
* 使用 synchronized volatile 锁机制保证 加载双重检测, 实现实例只会创建一次
*/
/** -------------------- 方式4 (推荐 JVM 保证) -------------------- */
public enum SingletonEnumObject {
/** */
INSTANCE;
public void testMethod() {
System.out.println("------testMethod()-----");
}
public static void main(String[] args) {
SingletonEnumObject.INSTANCE.testMethod();
}
}
/* 或者使用下面的方式 */
public enum SingletonEnum {
/***/
INSTANCE(new SingletonObject());
/***/
private SingletonObject singletonObject;
SingletonEnum(SingletonObject singletonObject) {
this.singletonObject = singletonObject;
}
}
public static SingletonObject getInstance4() {
return SingletonEnum.INSTANCE.singletonObject;
}
/*
* 分析:
* 使用枚举创建的单例模式:也是比较推荐的, 其实底层也是静态内部类的形式
*/
}
基本介绍
- 简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建出哪一种产品 类的实例。简单工厂模式是工厂模式家族中最简单实用的模式
- 简单工厂模式:定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
- 在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式.
代码
import java.util.Scanner;
/**
* 简单工厂模式也叫静态工厂模式,
* 因为也可以写成静态的形式如果不写成静态, 那就需要使用 依赖 ,组合 等形式进行关联
*
* 简单介绍:
* 定义了一个创建对象的类,由这个类来封装实例化对象的行为(代码)
*
* @author houyu
* @createTime 2019/11/16 14:48
*/
public class SimpleFactory {
/**
* 披萨
*/
public static class Pizza {
String name;
public void prepare() {
System.out.println(this.name + ": 准备阶段");
}
public void bake() {
System.out.println(this.name + ": 烘烤阶段");
}
public void cut() {
System.out.println(this.name + ": 切割阶段");
}
public void bax() {
System.out.println(this.name + ": 包装阶段");
}
}
/**
* 奶酪披萨
*/
public static class CheesePizza extends Pizza {
public CheesePizza() {
super.name = "奶酪披萨";
}
}
/**
* 希腊披萨
*/
public static class GreekPizza extends Pizza {
public GreekPizza() {
super.name = "希腊披萨";
}
}
/**
* 由 SimpleFactory 的 createPizza 创建披萨
* @param type 披萨类型
* @return 披萨实例对象
*/
public static Pizza createPizza(String type) {
switch(type) {
case "cheese":
return new CheesePizza();
case "greek":
return new GreekPizza();
default:
return null;
}
}
public static void main(String[] args) {
do {
System.out.print("请输入披萨类型:");
Scanner scanner = new Scanner(System.in);
String type = scanner.nextLine();
Pizza pizza = SimpleFactory.createPizza(type);
if(pizza == null) {
System.out.println("创建披萨失败");
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.bax();
} while(true);
/**
* 控制台:
*
* 请输入披萨类型:cheese
* 奶酪披萨: 准备阶段
* 奶酪披萨: 烘烤阶段
* 奶酪披萨: 切割阶段
* 奶酪披萨: 包装阶段
* 请输入披萨类型:greek
* 希腊披萨: 准备阶段
* 希腊披萨: 烘烤阶段
* 希腊披萨: 切割阶段
* 希腊披萨: 包装阶段
* 请输入披萨类型:123
* 创建披萨失败
*/
}
}
// 1.0
Calendar cal = Calendar.getInstance();
// 2.0
public static Calendar getInstance()
{
Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
return createCalendar(defaultTimeZone(aLocale), aLocale);
}
// 3.0
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
CalendarProvider provider =
LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale)
.getCalendarProvider();
if (provider != null) {
try {
return provider.getInstance(zone, aLocale);
} catch (IllegalArgumentException iae) {
// fall back to the default instantiation
}
}
Calendar cal = null;
if (aLocale.hasExtensions()) {
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype != null) {
switch (caltype) {
case "buddhist":
cal = new BuddhistCalendar(zone, aLocale);
break;
case "japanese":
cal = new JapaneseImperialCalendar(zone, aLocale);
break;
case "gregory":
cal = new GregorianCalendar(zone, aLocale);
break;
}
}
}
if (cal == null) {
// If no known calendar type is explicitly specified,
// perform the traditional way to create a Calendar:
// create a BuddhistCalendar for th_TH locale,
// a JapaneseImperialCalendar for ja_JP_JP locale, or
// a GregorianCalendar for any other locales.
// NOTE: The language, country and variant strings are interned.
if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
cal = new BuddhistCalendar(zone, aLocale);
} else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja"
&& aLocale.getCountry() == "JP") {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
}
return cal;
}
public class Test {
public static void main(String[] args) {
String type = "Student";
Penson person = PersonEnum.valueOf(type).getPerson();
System.out.println("person.toString() = " + person.toString());
}
}
abstract class Penson {
}
class Student extends Penson {
@Override
public String toString() {
final StringBuilder builder = new StringBuilder("Student{");
builder.append('}');
return builder.toString();
}
}
class Teacher extends Penson {
@Override
public String toString() {
final StringBuilder builder = new StringBuilder("Teacher{");
builder.append('}');
return builder.toString();
}
}
enum PersonEnum {
//
Student(new Student()),
Teacher(new Teacher());
private Penson person;
PersonEnum(Penson person) {
this.person = person;
}
public Penson getPerson() {
return person;
}
}
工厂方法模式:定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例 化推迟到子类。
代码实现
import java.util.Scanner;
/**
* 工厂方法模式:
* 定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例 化推迟到子类。
*
* @author houyu
* @createTime 2019/11/16 14:48
*/
public abstract class FactoryMethod {
/**
* 披萨
*/
public static class Pizza {
String name;
public void prepare() {
System.out.println(this.name + ": 准备阶段");
}
public void bake() {
System.out.println(this.name + ": 烘烤阶段");
}
public void cut() {
System.out.println(this.name + ": 切割阶段");
}
public void bax() {
System.out.println(this.name + ": 包装阶段");
}
}
/**
* 北京奶酪披萨
*/
public static class BJCheesePizza extends Pizza {
public BJCheesePizza() {
super.name = "北京奶酪披萨";
}
}
/**
* 北京希腊披萨
*/
public static class BJGreekPizza extends Pizza {
public BJGreekPizza() {
super.name = "北京希腊披萨";
}
}
/**
* 伦敦奶酪披萨
*/
public static class LDCheesePizza extends Pizza {
public LDCheesePizza() {
super.name = "伦敦奶酪披萨";
}
}
/**
* 伦敦希腊披萨
*/
public static class LDGreekPizza extends Pizza {
public LDGreekPizza() {
super.name = "伦敦希腊披萨";
}
}
/**
* 定义了一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例 化推迟到子类。
* @param type 披萨类型
* @return 披萨实例对象
*/
public abstract Pizza createPizza(String type);
/**
* 北京工厂
*/
public static class BJFactoryMethod extends FactoryMethod {
@Override
public Pizza createPizza(String type) {
switch(type) {
case "cheese":
return new BJCheesePizza();
case "greek":
return new BJGreekPizza();
default:
return null;
}
}
}
/**
* 伦敦工厂
*/
public static class LDFactoryMethod extends FactoryMethod {
@Override
public Pizza createPizza(String type) {
switch(type) {
case "cheese":
return new LDCheesePizza();
case "greek":
return new LDGreekPizza();
default:
return null;
}
}
}
public static void main(String[] args) {
do {
System.out.print("请输入地区:");
Scanner scanner = new Scanner(System.in);
String area = scanner.nextLine();
System.out.print("请输入披萨类型:");
String type = scanner.nextLine();
Pizza pizza = null;
if(area.equals("bj")) {
pizza = new BJFactoryMethod().createPizza(type);
} else if(area.equals("ld")) {
pizza = new LDFactoryMethod().createPizza(type);
}
if(pizza == null) {
System.out.println("创建披萨失败");
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.bax();
} while(true);
/*
* 控制台:
*
* 请输入地区:bj
* 请输入披萨类型:cheese
* 北京奶酪披萨: 准备阶段
* 北京奶酪披萨: 烘烤阶段
* 北京奶酪披萨: 切割阶段
* 北京奶酪披萨: 包装阶段
* 请输入地区:ld
* 请输入披萨类型:greek
* 伦敦希腊披萨: 准备阶段
* 伦敦希腊披萨: 烘烤阶段
* 伦敦希腊披萨: 切割阶段
* 伦敦希腊披萨: 包装阶段
* 请输入地区:xx
* 请输入披萨类型:xx
* 创建披萨失败
*
*/
}
}
基本介绍
- 抽象工厂模式:定义了一个 interface 用于创建相关或有依赖关系的对象簇,而无需指明具体的类
- 抽象工厂模式可以将简单工厂模式和工厂方法模式进行整合。
- 从设计层面看,抽象工厂模式就是对简单工厂模式的改进(或者称为进一步的抽象)。
- 将工厂抽象成两层,AbsFactory(抽象工厂) 和 具体实现的工厂子类。程序员可以根据创建对象类型使用对应 的工厂子类。这样将单个的简单工厂类变成了工厂簇,更利于代码的维护和扩展。
代码
import java.util.Scanner;
/**
* @author houyu
* @createTime 2019/11/16 16:29
*/
public class AbstractFactory {
/**
* 披萨
*/
public static class Pizza {
String name;
public void prepare() {
System.out.println(this.name + ": 准备阶段");
}
public void bake() {
System.out.println(this.name + ": 烘烤阶段");
}
public void cut() {
System.out.println(this.name + ": 切割阶段");
}
public void bax() {
System.out.println(this.name + ": 包装阶段");
}
}
/**
* 北京奶酪披萨
*/
public static class BJCheesePizza extends Pizza {
public BJCheesePizza() {
super.name = "北京奶酪披萨";
}
}
/**
* 北京希腊披萨
*/
public static class BJGreekPizza extends Pizza {
public BJGreekPizza() {
super.name = "北京希腊披萨";
}
}
/**
* 伦敦奶酪披萨
*/
public static class LDCheesePizza extends Pizza {
public LDCheesePizza() {
super.name = "伦敦奶酪披萨";
}
}
/**
* 伦敦希腊披萨
*/
public static class LDGreekPizza extends Pizza {
public LDGreekPizza() {
super.name = "伦敦希腊披萨";
}
}
/**
* 抽象工厂
*/
public interface BaseFactory {
/**
* 由实现子类具体实现
* @param type
*/
Pizza createPizza(String type);
}
/**
* 北京工厂
*/
public static class BJFactory implements BaseFactory {
@Override
public Pizza createPizza(String type) {
switch(type) {
case "cheese":
return new BJCheesePizza();
case "greek":
return new BJGreekPizza();
default:
return null;
}
}
}
/**
* 伦敦工厂
*/
public static class LDFactory implements BaseFactory {
@Override
public Pizza createPizza(String type) {
switch(type) {
case "cheese":
return new LDCheesePizza();
case "greek":
return new LDGreekPizza();
default:
return null;
}
}
}
public static void main(String[] args) {
do {
System.out.print("请输入地区:");
Scanner scanner = new Scanner(System.in);
String area = scanner.nextLine();
System.out.print("请输入披萨类型:");
String type = scanner.nextLine();
BaseFactory factory = null;
if(area.equals("bj")) {
factory = new BJFactory();
} else if(area.equals("ld")) {
factory = new LDFactory();
}
if(factory == null) {
System.out.println("创建披萨失败: 找不到工厂");
break;
}
Pizza pizza = factory.createPizza(type);
if(pizza == null) {
System.out.println("创建披萨失败: 找不到工厂");
break;
}
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.bax();
} while(true);
/*
* 请输入地区:bj
* 请输入披萨类型:cheese
* 北京奶酪披萨: 准备阶段
* 北京奶酪披萨: 烘烤阶段
* 北京奶酪披萨: 切割阶段
* 北京奶酪披萨: 包装阶段
* 请输入地区:ld
* 请输入披萨类型:greek
* 伦敦希腊披萨: 准备阶段
* 伦敦希腊披萨: 烘烤阶段
* 伦敦希腊披萨: 切割阶段
* 伦敦希腊披萨: 包装阶段
* 请输入地区:xx
* 请输入披萨类型:xx
* 创建披萨失败: 找不到工厂
*/
}
}