1、单例模式
意义:1、减少性能开销,避免对象频繁创建销毁;
2、避免资源多重占用,如同时对同一个文件做写操作
场景:1、唯一序列号
2、访问量
3、创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源
应用:spring中的每个bean(默认是饿汉,容器的初始化的时候就已经将所有的bean都加载进去了,@Lazy注解能设置成懒汉单例模式)
// 饿汉单例模式,对象初始化的时候就已经创建,性能更好
public class Singleton1 {
private static Singleton1 singleton1 = new Singleton1();
private Singleton1(){}
public static Singleton1 getInstance(){
return singleton1;
}
}
// 懒汉单例模式,对象第一次调用的时候创建,节省内存(Java中内部类是延迟加载的,不使用不加载)
class Singleton2 {
private Singleton2(){}
private static class SingletonFactory {
private static Singleton2 singleton2 = new Singleton2();
}
public static Singleton2 getInstance() {
return SingletonFactory.singleton2;
}
}
2、工厂模式
定义:把对象的创建和使用的过程分开。就是Class A 想调用 Class B ,那么A只是调用B的方法,B的实例化交给用工厂类
场景:1、创建复杂,需要一定代码量,需要重复创建
应用:1、MyBatis中SqlSessionFactory。
2、spring中的BeanFactory用到了简单工厂
// 抽象产品
interface Desk {
String getType();
}
// 具体产品
class WoodenDesk implements Desk{
private String type = "木质桌";
@Override
public String getType() {
return type;
}
}
// 具体产品
class PlasticDesk implements Desk {
private String type = "塑料桌";
@Override
public String getType() {
return type;
}
}
// 抽象产品
interface Chair {
String getType();
}
// 具体产品
class WoodenChair implements Chair {
private String type = "木质椅";
@Override
public String getType() {
return type;
}
}
// 具体产品
class PlasticChair implements Chair {
private String type = "塑料椅";
@Override
public String getType() {
return type;
}
}
/**
* 简单工厂:一个工厂类创建所有产品的对象
*/
public class SimpleFactory {
public Desk createDesk(String type){
Desk desk = null;
if (type.equals("Wooden")) {
desk = new WoodenDesk();
} else if (type.equals("Plastic")) {
desk = new PlasticDesk();
}
return desk;
}
}
/**
* 工厂方法:在简单工厂的基础上,把工厂类抽象化,每类产品都有一个工厂类
*/
// 工厂方法模式——抽象工厂
interface DeskFactory {
Desk createDesk();
}
// 工厂方法模式——具体工厂
class WoodenDeskFactory implements DeskFactory {
@Override
public Desk createDesk(){
return new WoodenDesk();
}
}
// 工厂方法模式——具体工厂
class PlasticDeskFactory implements DeskFactory {
@Override
public Desk createDesk() {
return new PlasticDesk();
}
}
/**
* 抽象工厂:相较于工厂方法增加产品族的概念,工厂方法里是一个工厂生产一类产品,抽象工厂
* 是一个工厂生产一组产品。
*/
// 抽象工厂模式——抽象工厂
interface FurnitureFactory {
Desk createDesk();
Chair createChair();
}
// 抽象工厂模式——具体工厂
class WoodenFurnitureFactory implements FurnitureFactory {
@Override
public Desk createDesk() {
return new WoodenDesk();
}
@Override
public Chair createChair() {
return new WoodenChair();
}
}
// 抽象工厂模式——具体工厂
class PlasticFurnitureFactory implements FurnitureFactory {
@Override
public Desk createDesk() {
return new PlasticDesk();
}
@Override
public Chair createChair() {
return new PlasticChair();
}
}
public static void main(String[] args) {
// 简单工厂
Desk wooden = new SimpleFactory().createDesk("Wooden");
System.out.println(wooden.getType());
Desk plastic = new SimpleFactory().createDesk("Plastic");
System.out.println(plastic.getType());
// 工厂方法
Desk desk = new WoodenDeskFactory().createDesk();
System.out.println(desk.getType());
Desk desk1 = new PlasticDeskFactory().createDesk();
System.out.println(desk1.getType());
// 抽象工厂
WoodenFurnitureFactory factory = new WoodenFurnitureFactory();
Chair chair = factory.createChair();
Desk desk2 = factory.createDesk();
System.out.println(chair.getType());
System.out.println(desk2.getType());
}
3、适配器模式
定义:将原本不兼容的接口融合在一起工作。比如要访问的接口A没有我们想要的方法,接口B中有合适的方法,但是不能改变访问接口(就是固定了通过A调)。
应用:1、spring中的AOP用到了类适配器,Spring提供了AspectJAfterReturningAdvice,AspectJMethodBeforeAdvice,AspectJAroundAdvice,AspectJAfterAdvice这几个advice中,AspectJAfterReturningAdvice和AspectJMethodBeforeAdvice没有实现MethodInterceptor接口,spring提供了AfterReturningAdviceAdapter和MethodBeforeAdviceAdapter实现了MethodInterceptor作为适配器
2、springmvc中HandlerAdapter
interface Ps2 {
void isPs2();
}
interface Usb {
void isUsb();
}
class Usber implements Usb {
@Override
public void isUsb() {
System.out.println("USB口");
}
}
/**
* 类适配器:定义一个适配器继承B的实现类BB并实现A,在A的抽象方法实现里调用B的方法
*/
public class Adapter extends Usber implements Ps2 {
@Override
public void isPs2() {
isUsb();
}
}
/**
* 对象适配器:定义个一个适配器实现A,在适配器里面通过构造器注入B的对象。在A的抽象方法实现里通过B
* 的对象调用B的方法
*/
class Adapter2 implements Ps2 {
private Usb usb;
public Adapter2(Usb usb){
this.usb = usb;
}
@Override
public void isPs2() {
usb.isUsb();
}
}
/**
* 接口适配器模式:当一个接口又很多方法,我们只需要其中一些方法,如果直接实现会导致实现类很臃肿,
* 我们定义一个抽象类(适配器)继承A,通过抽象类来实现A中的方法(空实现),
* 使用的时候创建适配器的子类重写需要用到的方法。
*/
interface A {
void a();
void b();
void c();
}
abstract class Adapter3 implements A {
public void a(){}
public void b(){}
public void c(){}
}
class Ashili extends Adapter3 {
public void a(){
System.out.println("实现A方法被调用");
}
}
public static void main(String[] args) {
Ps2 classAdapter = new Adapter();
classAdapter.isPs2(); // 类适配器
Ps2 objectAdapter = new Adapter2(new Usber());
objectAdapter.isPs2(); // 对象适配器
A interfaceAdapter = new Ashili();
interfaceAdapter.a(); // 接口适配器
}
4、装饰者模式
定义:在不改变对象结构的情况下动态的向一个现有的对象添加新的功能。相比于继承来说装饰者模式更灵 活。比如增加3种功能和不同功能组合,继承的话得写6个子类,装饰者只需要写3个,用的时候自己去组合
应用:1、spring中的Wrapper和Decorator
2、jdk的IO包
//抽象组件
interface Component {
void wearClothes();
void walkToWhere();
}
//具体组件
class Person implements Component {
@Override
public void wearClothes() {
System.out.println("穿什么呢。。");
}
@Override
public void walkToWhere() {
System.out.println("去哪里呢。。");
}
}
//抽象装饰者
public abstract class Decorator implements Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
public void wearClothes() {
component.wearClothes();
}
public void walkToWhere() {
component.walkToWhere();
}
}
//具体装饰者
class ConcreteDecoratorZero extends Decorator {
public ConcreteDecoratorZero(Component component) {
super(component);
}
public void goHome() {
System.out.println("进房子。。");
}
public void findMap() {
System.out.println("书房找找Map。。");
}
@Override
public void wearClothes() {
super.wearClothes();
goHome();
}
@Override
public void walkToWhere() {
super.walkToWhere();
findMap();
}
}
//具体装饰者
class ConcreteDecoratorFirst extends Decorator {
public ConcreteDecoratorFirst(Component component) {
super(component);
}
public void goClothespress() {
System.out.println("去衣柜找找看。。");
}
public void findPlaceOnMap() {
System.out.println("在Map上找找。。");
}
@Override
public void wearClothes() {
super.wearClothes();
goClothespress();
}
@Override
public void walkToWhere() {
super.walkToWhere();
findPlaceOnMap();
}
}
//具体装饰者
class ConcreteDecoratorTwo extends Decorator {
public ConcreteDecoratorTwo(Component component) {
super(component);
}
public void findClothes() {
System.out.println("找到一件D&G。。");
}
public void findTheTarget() {
System.out.println("在Map上找到神秘花园和城堡。。");
}
@Override
public void wearClothes() {
super.wearClothes();
findClothes();
}
@Override
public void walkToWhere() {
super.walkToWhere();
findTheTarget();
}
}
public static void main(String[] args) {
// 装饰者
Component person = new Person();
Decorator decorator = new ConcreteDecoratorTwo(new ConcreteDecoratorFirst(new
ConcreteDecoratorZero(person)));
decorator.wearClothes();
decorator.walkToWhere();
5、代理模式
定义:为对象提供一种代理,以控制对这个对象的访问。分为动态代理、静态代理。
动态代理有jdk动态代理、cglib,jdk动态代理是生成抽象角色的实现类,cglib是生成真实角色的子类,java1.6以后的版本不论单例多例jdk动态代理性能更高
应用:1、spring中AOP(JdkDynamicAopProxy、CglibAopProxy),spring默认使用jdk动态代理,当bean没有实现接口时用cglib,可以在spring配置里通过<aop:aspectj-autoproxy proxy-target-class="true"/>强制使用cglib
// 抽象角色
interface Star {
void confer(); //面谈
void sing(); //唱歌
void collectMoney(); //收钱
}
// 真实角色
class RealStar implements Star {
@Override
public void confer() {
System.out.println("RealStar.confer()");
}
@Override
public void sing() {
System.out.println("RealStar(周杰伦).sing()");
}
@Override
public void collectMoney() {
System.out.println("RealStar.collectMoney()");
}
}
// 代理角色-静态代理
public class StaticProxy implements Star {
private Star star;
public StaticProxy(Star star) { //到时候传进来真实的star
super();
this.star = star;
}
@Override
public void confer() {
System.out.println("ProxyStar.confer()");
}
@Override
public void sing() {
//其他事都能干,唯一不能干的就是唱歌,唱歌还是得要周杰伦本人来唱
star.sing(); //让他本人来唱
}
@Override
public void collectMoney() {
System.out.println("ProxyStar.collectMoney()");
}
}
/**
* 代理角色-JDK动态代理
* 动态代理优点:1、一个代理处理器能代理多个对象,而静态代理每个对象都要创建代理类
* 2、运行时自动创建代理类和实例化,不运行不创建
*/
class JDKProxyUtils{
public static Object getProxy(Object target, Supplier s){
return Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 和目标对象一样的类加载器
target.getClass().getInterfaces(), // 目标对象的接口列表
(proxy, method, args) -> { // InvocationHandler的匿名内部类lambda表达式写法
System.out.println(s.get());
//调用目标对象的方法
return method.invoke(target, args);
});
}
}
public static void main(String[] args) {
// 静态代理
Star real = new RealStar();
Star proxy = new StaticProxy(real);
proxy.confer();
proxy.sing();
proxy.collectMoney();
// jdk动态代理
Star proxy3 = (Star) JDKProxyUtils.getProxy(real, () -> "打印日志");
proxy3.confer();
proxy3.sing();
proxy3.collectMoney();
}
6、观察者模式
定义:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个被观察者。这个被观察者状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
应用:1、spring中的listener
2、java的util包自带Observable和Observer分别对应Subject和Observer的角色
// 抽象主题
interface Subject {
void attach(Observer observer);
void notify(String message);
}
// 具体主题
class ConcreteSubject implements Subject {
//储存订阅公众号的微信用户
private List<Observer> weixinUserlist = new ArrayList();
@Override
public void attach(Observer observer) {
weixinUserlist.add(observer);
}
@Override
public void notify(String message) {
for (Observer observer : weixinUserlist) {
observer.update(message);
}
}
}
// 抽象观察者
public interface Observer {
void update(String message);
}
// 具体观察者
class WeixinUser implements Observer {
private String name;
public WeixinUser(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "-" + message);
}
}
public static void main(String[] args) {
ConcreteSubject mSubscriptionSubject = new ConcreteSubject();
WeixinUser user1 = new WeixinUser("杨影枫");
WeixinUser user2 = new WeixinUser("月眉儿");
WeixinUser user3 = new WeixinUser("紫轩");
mSubscriptionSubject.attach(user1);
mSubscriptionSubject.attach(user2);
mSubscriptionSubject.attach(user3);
mSubscriptionSubject.notify("刘望舒的专栏更新了");
}
7、策略模式
定义:定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。
应用:spring实例化对象
//策略接口
public interface Strategy {
double getPrice(double standardPrice);
}
// 具体策略-新客户小批量
class NewCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("新客户小批量,不打折");
return standardPrice;
}
}
// 具体策略-新客户大批量
class NewCustomerManyStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("新客户大批量,打九折");
return standardPrice * 0.9;
}
}
// 具体策略-老客户小批量
class OldCustomerFewStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("老客户小批量,打八折");
return standardPrice * 0.8;
}
}
// 具体策略-老客户大批量
class OldCustomerManyStrategy implements Strategy {
@Override
public double getPrice(double standardPrice) {
System.out.println("老客户大批量,打八折");
return standardPrice * 0.7;
}
}
/**
* 负责和具体的策略交互,具体的算法和直接的客户端分离。
*/
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
super();
this.strategy = strategy;
}
public void getPrice(double standardPrice) {
System.out.println("报价为:" + strategy.getPrice(standardPrice));
}
}
public static void main(String[] args) {
Strategy s1 = new OldCustomerManyStrategy();
Context ctx = new Context(s1); //通过构造方法注入策略
ctx.getPrice(1000);
}
8、模板方法模式
定义:通过抽象类把不变部分的算法(基本方法)封装到父类实现,可变部分(模板方法)则可以通过子类继承来实现,允许子类通过重写钩子方法来改变基本方法的执行。
public abstract class Template {
// 模板方法
protected abstract void start(); //发动
protected abstract void stop(); //停止
protected abstract void alarm(); //鸣笛
protected abstract void engineBoom(); //轰鸣
// 基本方法
final public void run() { //车总归要跑
this.start();
this.engineBoom();
if (this.isAlarm()) { //想让它叫就叫,不想就不叫
this.alarm();
}
this.stop();
}
// 钩子方法
protected boolean isAlarm() { //我们加了一个判断方法,默认返回true
return true;
}
}
class HummerH1 extends Template {
@Override
public void start() {
System.out.println("H1发动……");
}
@Override
public void stop() {
System.out.println("H1停止……");
}
@Override
public void alarm() {
System.out.println("H1鸣笛……");
}
@Override
public void engineBoom() {
System.out.println("H1轰鸣……");
}
}
class HummerH2 extends Template {
private boolean alarmFlag = false; //判断标记
@Override
public void start() {
System.out.println("H2发动……");
}
@Override
public void stop() {
System.out.println("H2停止……");
}
@Override
public void alarm() {
System.out.println("H2鸣笛……");
}
@Override
public void engineBoom() {
System.out.println("H2轰鸣……");
}
@Override
protected boolean isAlarm() { //覆写isAlarm方法,返回判断标记
return this.alarmFlag;
}
public void setAlarm(boolean isAlarm) { //设置判断标记
this.alarmFlag = isAlarm;
}
}
public static void main(String[] args) {
HummerH1 h1 = new HummerH1();
h1.run();
HummerH2 h2 = new HummerH2();
h2.setAlarm(false);
h2.run();
}