一 . 总概念
设计模式是对代码开发经验的总结。
二 . 单例模式
概念:
一个类只有一个实例对象,无法使用 new 手动创建实例
构造器被 private 修饰,获得引用必须调用 getInstance 方法
Spring 中的 Bean 默认为单例
范例:
饿汉式
public class Singleton{
private static Singleton instance = new Singleton();
private Singleton() {};
public static Singleton getInstance() { return instance; }
}
分析:
类加载初始化后就完成了实例创建,多线程下一致性较好
不支持延迟加载
懒汉式
public class SingletonDemo {
//仅仅定义静态变量
private static SingletonDemo instance = null;
private SingletonDemo() {
}
//使用synchronized 同步关键字,保证该方法多线程下只能单个线程使用
public synchronized static SingletonDemo getInstance() {
return instance!=null?instance:new SingletonDemo();
}
}
分析:
类加载初始化时仅定义了静态变量
调用 getInstance 方法时才会创建实例
在方法前加上 synchronized 关键字可以让操作变的线程安全
使用了延迟加载
假如没有 synchronized 关键字,多线程操作可能会创建多个实例(数个线程同时在创建),浪费资源
DCL(Double Check Lock)
public class Singleton {
//通过volatile关键字来确保安全
private volatile static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null){
synchronized (Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
分析:
这个线程安全的单例模式跟进了一步
单纯的 synchronized 无法保障线程安全,因为指令会重排序,导致其他线程访问时对象仍未创立
根据上图分析
需要 volatile 关键字,来确保有序性。
二 . 观察者模式
概念:
有一个事件对象,多个观察者对象监听(依赖)着事件对象。
事件对象更新后,所有观察者对象都得到通知和更新
是 Spring 事件驱动的模型
Spring 中整合了一套观察者模式的接口:
ApplicationContext:容器对象
ApplicationEvent:事件对象
ApplicationListener:事件监听对象
范例:
创建监听对象
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
/*****
* @Description: 创建监听对象
****/
public class ApplicationEventListener implements ApplicationListener<ContextRefreshedEvent> {
//发生指定事件后会触发该方法执行
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
ApplicationContext applicationContext = contextRefreshedEvent.getApplicationContext();
System.out.println("监听到容器初始化完成!");
}
}
将监听对象添加到容器中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--配置文件中配置-->
<bean id="applicationEventListener" class="com.tukecloud.spring.ApplicationEventListener"/>
</beans>
测试调用
public class SpringContextTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-event.xml");
}
}
三 . 装饰器模式
概念:
创建一个装饰器类对原有的一个类进行包装,实现新的功能
范例:
//基础接口
public interface Component {
public void biu();
}
//具体实现类
public class ConcretComponent implements Component {
public void biu() {
System.out.println("biubiubiu");
}
}
//装饰类
public class Decorator implements Component {
public Component component;
public Decorator(Component component) {
this.component = component;
}
public void biu() {
this.component.biu();
}
}
//具体装饰类
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void biu() {
System.out.println("ready?go!");
this.component.biu();
}
}
四 . 适配器模式
概念
将一个类的接口转换成指定的接口,实现兼容
范例
Java版:接口A
public class Phone {
public void typecPhone() {
System.out.println("信息从Typec口的手机输出。");
}
}
接口B
public interface Vga {
void vgaInterface();
}
适配器
public class Typec2Vga1 extends Phone implements Vga{
@Override
public void vgaInterface() {
// TODO Auto-generated method stub
typecPhone();
System.out.println("接收到Type-c口信息,信息转换成VGA接口中...");
System.out.println("信息已转换成VGA接口,显示屏可以对接。");
}
}
Spring 版
Spring 中适配器模式被整合成了 Advice 和 Adapter 功能
接口A
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, Object target) throws Throwable;
}
接口B
public interface AdvisorAdapter {
// 判断通知类型是否匹配
boolean supportsAdvice(Advice advice);
// 获取对应的拦截器
MethodInterceptor getInterceptor(Advisor advisor);
}
适配器
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
// 通知类型匹配对应的拦截器
return new MethodBeforeAdviceInterceptor(advice);
}
}
五 . 工厂方法模式
1.简单工厂模式
范例
接口类
public interface Car {
String getName();
}
实现类们
// 实现类 A
public class Audi implements Car {
@Override
public String getName() {
return "audi";
}
}
// 实现类 B
public class Benz implements Car {
@Override
public String getName() {
return "benz";
}
}
工厂类
public class SimpleFactory {
public Car getCar(String name){
if("BMW".equalsIgnoreCase(name)){
return new Bmw();
}else if("Benz".equalsIgnoreCase(name)){
return new Benz();
}else{
System.out.println("这个产品产不出来");
return null;
}
}
}
分析
一个抽象的接口,多个接口的实现类,
一个工厂类,用来确定具体实例化那个抽象的实现类
2. 工厂方法模式
范例
抽象类
public interface Factory {
Car getCar();
}
工厂类们
/**
*生产奥迪的工厂
*/
public class AudiFactory implements Factory {
@Override
public Car getCar() {
return new Audi();
}
}
/**
*生产奔驰的工厂
*/
public class BenzFactory implements Factory {
@Override
public Car getCar() {
return new Benz();
}
}
/**
* 生产宝马的工厂
*/
public class BmwFactory implements Factory {
@Override
public Car getCar() {
return new Bmw();
}
}
测试类
public class FactoryTest {
public static void main(String[] args) {
//1.首先先创建一个奥迪工厂出来
Factory factory = new AudiFactory();
//2.然后根据工厂得到奥迪车,具体的造车工厂交给工厂来完成
System.out.println(factory.getCar());
factory = new BmwFactory();
System.out.println(factory.getCar());
}
}
分析
一个抽象类接口,数个具体的工厂类实现
调用时,接口对象的生成方法是 new 一个具体的工厂类
3. 抽象工厂模式
范例
抽象类
public abstract class AbstractFactory {
/**
* 得到奥迪的车
* @return
*/
public abstract Car getAudiCar();
/**
* 得到奔驰的车
* @return
*/
public abstract Car getBenzCar();
/**
* 得到宝马的车
* @return
*/
public abstract Car getBmwCar();
}
实现类
public class CarFactory extends AbstractFactory {
@Override
public Car getAudiCar() {
return new Audi();
}
@Override
public Car getBenzCar() {
return new Benz();
}
@Override
public Car getBmwCar() {
return new Bmw();
}
}
调用测试类
public class AbstractFactoryTest {
public static void main(String[] args) {
//1.先创建具体抽象工厂
AbstractFactory abstractFactory = new CarFactory();
//2.根据具体的抽象工厂得到车
Car audi = abstractFactory.getAudiCar();
System.out.println(audi.getName());
}
}
分析
一个抽象类中有数个抽象方法。
实现类调用不同的工厂类分别实现不同方法
调用时,调用指定方法实例化抽象类对象