文章目录
一. 工厂模式
主要分:简单工厂、抽象工厂(多类产品即多个产品接口)、工厂方法(一类产品)模式三种,主要目的是解耦。
1. 简单工厂模式
- 创建产品接口和产品工厂,产品实现接口
- 工厂类通过传入类型,创建相应产品(通过接口引用接收)
即:总工厂负责具体产品创建
(1). 产品接口
public interface Product {
public String getPrice();
}
(2). 冰箱产品(实现产品接口)
public class Refrigerator implements Product {
@Override
public String getPrice() {
String price = "25.23";
System.out.println("我是冰箱,我的价格是:" + price);
return price;
}
}
(3). 洗衣机产品(实现产品接口)
public class WashingMachine implements Product {
@Override
public String getPrice() {
String price = "99.99";
System.out.println("我是洗衣机,我的价格是:" + price);
return price;
}
}
(4). 产品工厂
public class ProductFactory {
/** 产品1-冰箱 */
private static final int PROC_1 = 1;
/** 产品2-洗衣机 */
private static final int PROC_2 = 2;
public static Product getProduct(int type) {
if(type == PROC_1) {
return new Refrigerator();
} else if(type == PROC_2) {
return new WashingMachine();
} else {
System.out.println("没有该类型产品...");
return null;
}
}
}
(5). 测试
public class TestMain {
public static void main(String[] args) {
Product product = ProductFactory.getProduct(1);
product.getPrice();
}
}
(6). 输出
我是冰箱,我的价格是:25.23
2. 工厂方法模式
定义总工厂接口,各个产品自己有工厂类,工厂类实现总工厂接口的相应方法。
即:总工厂只定义方法,各个产品工厂实现总工厂方法。(工厂不负责产品创建)
使用场景:一类产品族,多个产品
(1). 总工厂类
public interface ProductFactory {
public Product getProduct();
}
(2). 产品工厂
public class RefrigeratorFactory implements ProductFactory {
@Override
public Product getProduct() {
return new Refrigerator();
}
}
public class WashingMachineFactory implements ProductFactory {
@Override
public Product getProduct() {
return new WashingMachine();
}
}
(3). 测试
public class TestMain {
public static void main(String[] args) {
ProductFactory washingMachineFactory = new WashingMachineFactory();
System.out.println(washingMachineFactory.getProduct().getPrice());
}
}
(4). 结果
我是洗衣机,我的价格是:99.99
99.99
3. 抽象工厂模式
类似于工厂方法模式,区别在于工厂方法针对一类产品,而抽象工厂可以针对多类产品(产品的工厂提供创建多类产品的方法)。
即:产品接口新增了一个的处理过程(工厂新增一个创建新产品的方法)
场景:系统的产品多于一个产品族,而系统只消费某一族的产品。
(1). 现在产品升级了,有新产品加入,也有原来的产品,新产品接口及产品如下
public interface NewProduct {
public String getPrice();
}
public class NewRefrigerator implements NewProduct {
@Override
public String getPrice() {
String price = "125.23";
System.out.println("我是新冰箱,我的价格是:" + price);
return price;
}
}
public class NewWashingMachine implements NewProduct {
@Override
public String getPrice() {
String price = "199.99";
System.out.println("我是新洗衣机,我的价格是:" + price);
return price;
}
}
(2). 现在的工厂就不止创建老产品了,也要能创建新产品(添加一个创建新产品的方法),总工厂修改如下:
public interface ProductFactory {
public Product getProduct();
public NewProduct getNewProduct();
}
(3). 自然产品工厂也要新增方法,如下
public class WashingMachineFactory implements ProductFactory {
@Override
public Product getProduct() {
return new WashingMachine();
}
@Override
public NewProduct getNewProduct() {
return new NewWashingMachine();
}
}
public class RefrigeratorFactory implements ProductFactory {
@Override
public Product getProduct() {
return new Refrigerator();
}
@Override
public NewProduct getNewProduct() {
return new NewRefrigerator();
}
}
(4). 好了,现在既可以创建新产品,也可以创建老产品,测试:
public class TestMain {
public static void main(String[] args) {
ProductFactory washingMachineFactory = new WashingMachineFactory();
System.out.println(washingMachineFactory.getProduct().getPrice());
System.out.println(washingMachineFactory.getNewProduct().getPrice());
}
}
(5). 结果
我是洗衣机,我的价格是:99.99
99.99
我是新洗衣机,我的价格是:199.99
199.99
二. 适配器模式
把类的接口转变为满足要求的另一种接口,从而使因为接口不匹配无法在一起工作的两个类能够在一起工作。一般分为类适配器和对象适配器两种。
1. 类适配器(实现接口,继承类)
(1). 原始类
public class SourceClass {
public void method1(){
System.out.println("execute method1...");
}
}
(2). 目标接口
public interface TargetInterface {
public void method1();
public void method2();
}
(3). 适配器
public class ClassAdapter extends SourceClass implements TargetInterface {
@Override
public void method2() {
System.out.println("execute method2...");
}
}
2. 对象适配器
适配器类实现目标接口,添加源类作为成员变量,并实现目标接口方法(以成员变量去实现)。
(1). 源类
public class ObjectTarget {
public void method1 () {
System.out.println("我只有method1方法...");
}
}
(2). 目标接口
public interface TargetInterface {
public void method1();
// 目标类没有此方法
public void method2();
}
(3). 适配器类
public class AdapterClass implements TargetInterface {
/** 源类作为成员变量 */
private ObjectTarget objectTarget;
/**
* <p>创建时赋值</p>
* @param objectTarget
* @author FRH
* @time 2018年12月12日上午10:48:58
* @version 1.0
*/
public AdapterClass(ObjectTarget objectTarget) {
this.objectTarget = objectTarget;
}
@Override
public void method1() {
// 源类去实现
objectTarget.method1();
}
@Override
public void method2() {
System.out.println("自己去实现method2...");
}
}
三. 代理模式
在不改变源码的情况下,实现目标对象功能的拓展。主要分静态代理、动态代理(JDK代理)和Cglib代理三种。(静态代理和动态代理的目标对象必须实现一个或多个接口,不然的话,可以用Cglib代理)
1. 静态代理
代理类实现源接口,并源接口为成员变量(在创建代理类是赋值),实现代理方法,实现中调用源接口方法共同实现。
缺点:接口层发生变化,代理类也得修改。
(1). 目标接口
public interface TargetInterface {
public void method1();
}
(2). 目标实现
public class TargetImpl implements TargetInterface {
@Override
public void method1() {
System.out.println("我是源实现...");
}
}
(3). 代理类
public class ProxyClass implements TargetInterface {
/** 源接口为成员变量 */
private TargetInterface targetInterface;
public ProxyClass(TargetInterface targetInterface) {
this.targetInterface = targetInterface;
}
@Override
public void method1() {
System.out.println("执行前工作...");
targetInterface.method1(); // 开始执行代理方法
System.out.println("执行后工作...");
}
}
(4). 测试
public class TestMain {
public static void main(String[] args) {
TargetInterface target = new TargetImpl();
ProxyClass proxyClass = new ProxyClass(target);
proxyClass.method1();
}
}
(5). 结果
执行前工作...
我是源实现...
执行后工作...
2. 动态代理(也称JDK代理)
运行中动态返回代理对象,调用JDK自带的Proxy类的静态方法newProxyInstance即可。
优点:不管接口怎么变,都能满足
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h );
// ClassLoader loader:指定当前目标对象使用类加载器,写法固定
// Class<?>[] interfaces:目标对象实现的接口的类型,写法固定
// InvocationHandler h:事件处理接口,需传入一个实现类,一般直接使用匿名内部类
(1). 示例
public class TestMain {
public static void main(String[] args) {
final TargetInterface target = new TargetImpl();
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("执行前工作...");
Object returnValue = method.invoke(target, args);
System.out.println("执行后工作...");
return returnValue;
}
});
proxy.method1();
}
}
(2). 结果
执行前工作...
我是源实现...
执行后工作...
3. Cglib代理
代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。
前提条件:
需要引入cglib的jar文件,由于Spring的核心包中已经包括了Cglib功能,所以也可以直接引入spring-core-XXX.jar
目标类不能为final
目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
(1). 代理对象
public class ProxyFactory implements MethodInterceptor {
/** 目标对象 */
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/**
* <p>给目标对象创建一个代理对象</p>
* @return Object 代理对象
* @author FRH
* @time 2018年12月12日上午11:26:20
* @version 1.0
*/
public Object getProxyInstance() {
// 1.工具类
Enhancer en = new Enhancer();
// 2.设置父类
en.setSuperclass(target.getClass());
// 3.设置回调函数
en.setCallback(this);
// 4.创建子类(代理对象)
return en.create();
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("执行前工作...");
Object returnValue = arg1.invoke(target, arg2);
System.out.println("执行后工作...");
return returnValue;
}
}
(2). 测试
public class TestMain {
public static void main(String[] args) {
TargetInterface target = new TargetImpl();
TargetImpl proxy = (TargetImpl) new ProxyFactory(target).getProxyInstance();
proxy.method1();
}
}
(3). 结果
执行前工作...
我是源实现...
执行后工作...
静态代理与动态代理区别:
- 静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
- 静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。
- 动态代理是实现 JDK 里的 InvocationHandler 接口的 invoke 方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过 Proxy 里的 newProxyInstance 得到代理对象。
- AOP编程就是基于动态代理实现的,比如著名的 Spring 框架、 Hibernate 框架等等都是动态代理的使用例子。
四. 模板方法模式
定义一个抽象类,将部分逻辑或构造方法或具体构造函数定义实现,然后定义一些抽象方法迫使子类实现剩余逻辑。这个定义好的模板提供了轮廓,子类只需要具体填充实现即可。典型使用如Servlet,doGet()和doPost()都是钩子方法(规则一般以do开头)。
(1). 模板类
public abstract class AbstractTemplate {
/**
* <p>模板方法</p> void
* @author FRH
* @time 2018年12月12日下午1:35:26
* @version 1.0
*/
public void templateMethod() {
// 调用基本方法(具体方法)
changelessMethod();
// 子类需要实现的方法(抽象方法)
needMethod();
// 子类可变的方法(钩子方法)
doMethod();
}
/**
* <p>子类可选择实现(钩子方法)</p> void
* @author FRH
* @time 2018年12月12日下午1:35:48
* @version 1.0
*/
protected void doMethod() {}
/**
* <p>固定方法(具体方法)</p> void
* @author FRH
* @time 2018年12月12日下午1:35:59
* @version 1.0
*/
private final void changelessMethod() {
System.out.println("固定方法由我实现,子类不可改变...");
}
/**
* <p>子类需要实现方法(抽象方法)</p> void
* @author FRH
* @time 2018年12月12日下午1:36:25
* @version 1.0
*/
protected abstract void needMethod();
}
(2). 子实现类
public class ChildClass extends AbstractTemplate {
@Override
protected void needMethod() {
System.out.println("模板要求我实现的方法...");
}
protected void doMethod() {
System.out.println("我选择实现的方法(钩子方法)...");
}
}
五. 单例模式
分法比较多,一般分懒汉模式(全局单例在第一次使用时被创建)和饿汉模式(全局单例在类加载时被创建),其它都是其变种。
1. 懒汉式写法1(只能是单线程,多线程有一定几率出现多实例,如同时进入if判断)
public class SingleModel {
/** 私有的成员 */
private static SingleModel singleModule;
/**
* <p>私有构造</p>
* @author FRH
* @time 2018年12月12日下午1:57:37
* @version 1.0
*/
private SingleModel(){}
/**
* <p>获取实例</p>
* @return SingleModel
* @author FRH
* @time 2018年12月12日下午1:57:46
* @version 1.0
*/
public static SingleModel getSingleModel () {
if(singleModule == null) singleModule = new SingleModel();
return singleModule;
}
}
2. 懒汉式写法2(在写法1上加同步锁,避免多线程访问问题,不过效率低了)
public class SingleModel {
/** 私有的成员 */
private static SingleModel singleModule;
/**
* <p>私有构造</p>
* @author FRH
* @time 2018年12月12日下午1:57:37
* @version 1.0
*/
private SingleModel(){}
/**
* <p>获取实例</p>
* @return SingleModel
* @author FRH
* @time 2018年12月12日下午1:57:46
* @version 1.0
*/
public static synchronized SingleModel getSingleModel () {
if(singleModule == null) singleModule = new SingleModel();
return singleModule;
}
}
3. 懒汉式3(锁加在对象判断为空后,继续判断,复杂)
public class SingleModel {
/** 私有的成员 */
private static SingleModel singleModule;
/**
* <p>私有构造</p>
* @author FRH
* @time 2018年12月12日下午1:57:37
* @version 1.0
*/
private SingleModel(){}
/**
* <p>获取实例</p>
* @return SingleModel
* @author FRH
* @time 2018年12月12日下午1:57:46
* @version 1.0
*/
public static SingleModel getSingleModel () {
if(singleModule == null) {
synchronized(SingleModel.class) {
if(singleModule == null) singleModule = new SingleModel();
}
}
return singleModule;
}
}
4. 懒汉式-静态内部类(建议,第一次使用时创建)
public class SingleModel {
/**
* <p>私有构造</p>
* @author FRH
* @time 2018年12月12日下午1:57:37
* @version 1.0
*/
private SingleModel(){}
/**
* <p>静态内部类,创建实例,第一次使用时创建</p>
* @author FRH
* @time 2018年12月12日下午2:09:02
* @version 1.0
*/
private static class SingleModelHolder {
private final static SingleModel instance = new SingleModel();
}
/**
* <p>获取实例</p>
* @return SingleModel
* @author FRH
* @time 2018年12月12日下午1:57:46
* @version 1.0
*/
public static SingleModel getSingleModel () {
return SingleModelHolder.instance;
}
}
5. 饿汉式
public class SingleModel {
/** 私有的成员 */
private static SingleModel singleModule = new SingleModel();
/**
* <p>私有构造</p>
* @author FRH
* @time 2018年12月12日下午1:57:37
* @version 1.0
*/
private SingleModel(){}
/**
* <p>获取实例</p>
* @return SingleModel
* @author FRH
* @time 2018年12月12日下午1:57:46
* @version 1.0
*/
public static SingleModel getSingleModel () {
return singleModule;
}
}