跟着狂神学设计模式
设计模式
什么是设计模式
学习设计模式意义
设计模式基本要素
GoF23
OOP七大原则
工厂模式
静态工厂模式
Car
package com.kuang.factory.simple;
public interface Car {
void name();
}
Tesla
package com.kuang.factory.simple;
public class Tesla implements Car {
public void name() {
System.out.println("特斯拉");
}
}
WuLing
package com.kuang.factory.simple;
public class WuLing implements Car {
public void name() {
System.out.println("五菱宏光");
}
}
CarFactory
package com.kuang.factory.simple;
public class CarFactory {
//静态工厂模式
//增加一个新的产品如果不修改代码做不到
//方法一
public static Car getCar(String car){
if (car.equals("五菱宏光")){
return new WuLing();
}else if(car.equals("特斯拉")){
return new Tesla();
}else return null;
}
//方法二
public static Car getWuLing(){
return new WuLing();
}
public static Car getTesla(){
return new Tesla();
}
}
Consumer
package com.kuang.factory.simple;
public class Consumer {
public static void main(String[] args) {
//接口,所有实现类
Car wuLing = new WuLing();
Car tesla = new Tesla();
wuLing.name();
tesla.name();
wuLing=CarFactory.getCar("五菱宏光");
tesla=CarFactory.getCar("特斯拉");
wuLing.name();
tesla.name();
}
}
思想
工厂方法模式
Car
package com.kuang.factory.method;
public interface Car {
void name();
}
CarFactory
package com.kuang.factory.method;
public interface CarFactory {
//工厂方法模式
Car getCar();
}
Tesla
package com.kuang.factory.method;
public class Tesla implements Car {
public void name() {
System.out.println("特斯拉");
}
}
TeslaFactory
package com.kuang.factory.method;
public class TeslaFactory implements CarFactory {
public Car getCar() {
return new Tesla();
}
}
WuLing
package com.kuang.factory.method;
public class WuLing implements Car {
public void name() {
System.out.println("五菱宏光");
}
}
WuLingFactory
package com.kuang.factory.method;
public class WuLingFactory implements CarFactory {
public Car getCar() {
return new WuLing();
}
}
Consumer
package com.kuang.factory.method;
import com.kuang.factory.simple.CarFactory;
import com.kuang.factory.simple.Tesla;
import com.kuang.factory.simple.WuLing;
public class Consumer {
public static void main(String[] args) {
//接口,所有实现类
Car wuLing = new WuLingFactory().getCar();
Car tesla = new TeslaFactory().getCar();
wuLing.name();
tesla.name();
}
//结构复杂度: simple
//代码复杂度: simple
//编程复杂度: simple
//管理上的复杂度: simple
//舰据设计原则:工厂方法模式!
//根据实际业务:简单工厂模式!
}
结构
抽象工厂模式
代码实现
IPhoneProduct
package com.kuang.factory.abstract1;
//手机产品接口
public interface IPhoneProduct {
void start();
void shutdown();
void call();
void sendMsg();
}
IRouterProduct
package com.kuang.factory.abstract1;
//路由器产品接口
public interface IRouterProduct {
void start();
void shutdown();
void openWifi();
void setting();
}
IProductFactory
package com.kuang.factory.abstract1;
//抽象产品工厂
public interface IProductFactory {
//生产手机
IPhoneProduct iPhoneProduct();
//生产路由器
IRouterProduct iRouterProduct();
}
XiaomiPhone
package com.kuang.factory.abstract1;
public class XiaomiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("小米开机");
}
@Override
public void shutdown() {
System.out.println("小米关机");
}
@Override
public void call() {
System.out.println("小米打电话");
}
@Override
public void sendMsg() {
System.out.println("小米发信息");
}
}
XiaomiRouter
package com.kuang.factory.abstract1;
public class XiaomiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("小米开启路由器");
}
@Override
public void shutdown() {
System.out.println("小米关闭路由器");
}
@Override
public void openWifi() {
System.out.println("小米开启Wifi");
}
@Override
public void setting() {
System.out.println("小米设置路由器");
}
}
XiaomiFactory
package com.kuang.factory.abstract1;
public class XiaomiFactory implements IProductFactory {
@Override
public IPhoneProduct iPhoneProduct() {
return new XiaomiPhone();
}
@Override
public IRouterProduct iRouterProduct() {
return new XiaomiRouter();
}
}
Client
package com.kuang.factory.abstract1;
public class Client {
public static void main(String[] args) {
System.out.println("=================小米系列产品==============");
XiaomiFactory xiaomiFactory = new XiaomiFactory();
IPhoneProduct iPhoneProduct = xiaomiFactory.iPhoneProduct();
iPhoneProduct.start();
IRouterProduct iRouterProduct = xiaomiFactory.iRouterProduct();
iRouterProduct.start();
}
}
运行结果
=================小米系列产品==============
小米开机
小米开启路由器
案例较为简单,只做了小米这一个,有兴趣可自行补充华为
结构图
小结
建造者模式
角色分析
代码实现
Product
package com.kuang.builder;
//产品,房子
public class Product {
private String builderA;
private String builderB;
private String builderC;
private String builderD;
public String getBuilderA() {
return builderA;
}
public void setBuilderA(String builderA) {
this.builderA = builderA;
}
public String getBuilderB() {
return builderB;
}
public void setBuilderB(String builderB) {
this.builderB = builderB;
}
public String getBuilderC() {
return builderC;
}
public void setBuilderC(String builderC) {
this.builderC = builderC;
}
public String getBuilderD() {
return builderD;
}
public void setBuilderD(String builderD) {
this.builderD = builderD;
}
@Override
public String toString() {
return "Product{" +
"builderA='" + builderA + '\'' +
", builderB='" + builderB + '\'' +
", builderC='" + builderC + '\'' +
", builderD='" + builderD + '\'' +
'}';
}
}
Builder
package com.kuang.builder;
//抽象的建造者:方法
public abstract class Builder {
abstract void builderA();//地基
abstract void builderB();//钢筋工程
abstract void builderC();//铺电线
abstract void builderD();//粉刷
//完工:得到产品
abstract Product getProduct();
}
Worker
package com.kuang.builder;
//具体的建造者:工人
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
void builderA() {
product.setBuilderA("地基");
System.out.println("地基");
}
@Override
void builderB() {
product.setBuilderB("钢筋工程");
System.out.println("钢筋工程");
}
@Override
void builderC() {
product.setBuilderC("铺电线");
System.out.println("铺电线");
}
@Override
void builderD() {
product.setBuilderD("粉刷");
System.out.println("粉刷");
}
@Override
Product getProduct() {
return product;
}
}
Director
package com.kuang.builder;
//指挥:核心,负责指挥构建一个工程,工程如何构建,由它决定
public class Director {
//指挥工人按照顺序建房子
public Product build(Builder builder){
builder.builderA();
builder.builderB();
builder.builderC();
builder.builderD();
return builder.getProduct();
}
}
Test
package com.kuang.builder;
public class Test {
public static void main(String[] args) {
//指挥
Director director = new Director();
//指挥具体的工人完成产品
Product build = director.build(new Worker());
System.out.println(build.toString());
}
}
建造者模式的意图和适用场景(拓展)
建造者的参与者(拓展)
举例说明:设计房屋(拓展)
总结(拓展)
代码再实现
Product
package com.kuang.builder.demo02;
//产品:套餐
public class Product {
private String BuildA ="汉堡";
private String BuildB ="可乐";
private String BuildC ="薯条";
private String BuildD ="甜点";
public String getBuildA() {
return BuildA;
}
public void setBuildA(String buildA) {
BuildA = buildA;
}
public String getBuildB() {
return BuildB;
}
public void setBuildB(String buildB) {
BuildB = buildB;
}
public String getBuildC() {
return BuildC;
}
public void setBuildC(String buildC) {
BuildC = buildC;
}
public String getBuildD() {
return BuildD;
}
public void setBuildD(String buildD) {
BuildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"BuildA='" + BuildA + '\'' +
", BuildB='" + BuildB + '\'' +
", BuildC='" + BuildC + '\'' +
", BuildD='" + BuildD + '\'' +
'}';
}
}
Builder
package com.kuang.builder.demo02;
//建造者
public abstract class Builder {
abstract Builder BuildA(String msg);//"汉堡";
abstract Builder BuildB(String msg);//"可乐";
abstract Builder BuildC(String msg);//"薯条";
abstract Builder BuildD(String msg);//"甜点";
abstract Product getProduct();
}
Worker
package com.kuang.builder.demo02;
public class Worker extends Builder {
private Product product;
public Worker() {
product = new Product();
}
@Override
Builder BuildA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder BuildB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder BuildC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder BuildD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
Test
package com.kuang.builder.demo02;
public class Test {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
//可以按默认走,也可以自由组合
Product product = worker.BuildA("全家桶").BuildB("雪碧").getProduct();
System.out.println(product.toString());
}
}
运行结果
Product{BuildA='全家桶', BuildB='雪碧', BuildC='薯条', BuildD='甜点'}
优缺点
应用场景以及与抽象工厂模式对比
原型模式
代码实现
Video
package com.kuang.prototype.demo01;
import java.util.Date;
/*
1..实现一个接口Cloneable
2.重写一个方法clone()
*/
//Video
public class Video implements Cloneable { //无良up 主,克隆别人的视频! .
private String name;
private Date createTime;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public Video() {
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
}
Bilibili
package com.kuang.prototype.demo01;
import java.util.Date;
/*
客户端:克隆
*/
public class Bilibili {
public static void main(String[] args) throws CloneNotSupportedException {
//原型对象v1
Date date = new Date();
Video v1 = new Video("狂神说Java", date);
//v1克隆v2
//Video v2 = new Video( "狂神说Java", date);
Video v2 = (Video) v1.clone();
System.out.println("v1=>" + v1);
System.out.println("v2=>" + v2);
date.setTime(22131231);
System.out.println("++++++++++++++++++++++++++++++++++++++");
System.out.println("v1=>" + v1);
System.out.println("v2=>" + v2);
}
}
运行结果
v1=>Video{name='狂神说Java', createTime=Thu Dec 10 23:52:48 CST 2020}
v2=>Video{name='狂神说Java', createTime=Thu Dec 10 23:52:48 CST 2020}
++++++++++++++++++++++++++++++++++++++
v1=>Video{name='狂神说Java', createTime=Thu Jan 01 14:08:51 CST 1970}
v2=>Video{name='狂神说Java', createTime=Thu Jan 01 14:08:51 CST 1970}
原理理解
代码再实现
Video
package com.kuang.prototype.demo02;
import java.util.Date;
/*
1..实现一个接口Cloneable
2.重写一个方法clone()
*/
//Video
public class Video implements Cloneable { //无良up 主,克隆别人的视频! .
private String name;
private Date createTime;
@Override
protected Object clone() throws CloneNotSupportedException {
Object obj = super.clone();
//实现深克隆~序列化, 反序列化
Video v = (Video) obj;
v.createTime = (Date) this.createTime.clone();//将这个对象的属性也进行克隆~
return v;
}
public Video() {
}
public Video(String name, Date createTime) {
this.name = name;
this.createTime = createTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Video{" +
"name='" + name + '\'' +
", createTime=" + createTime +
'}';
}
}
Bilibili
package com.kuang.prototype.demo02;
import java.util.Date;
/*
客户端:克隆
*/
public class Bilibili {
public static void main(String[] alrgs) throws CloneNotSupportedException {
//原型对象v1
Date date = new Date();
Video v1 = new Video("狂神说Java", date);
//v1克隆v2
//Video v2 = new Video( "狂神说Java", date);
Video v2 = (Video) v1.clone();
System.out.println("v1=>" + v1);
System.out.println("v2=>" + v2);
date.setTime(22131231);
System.out.println("+++++++++++++++++++++++++++++++++++");
System.out.println("v1=>" + v1);
System.out.println("v2=>" + v2);
}
}
运行结果
v1=>Video{name='狂神说Java', createTime=Thu Dec 10 23:56:38 CST 2020}
v2=>Video{name='狂神说Java', createTime=Thu Dec 10 23:56:38 CST 2020}
+++++++++++++++++++++++++++++++++++
v1=>Video{name='狂神说Java', createTime=Thu Jan 01 14:08:51 CST 1970}
v2=>Video{name='狂神说Java', createTime=Thu Dec 10 23:56:38 CST 2020}
适配器模式
结构型模式
代码实现
Adaptee
package com.kuang.adapter;
//要被适配的类:网线
public class Adaptee {
public void request() {
System.out.println("连接网线上网");
}
}
Adapter
package com.kuang.adapter;
//真正的适配器,需 要连接USB,连接网线~
public class Adapter extends Adaptee implements NetToUsb {
@Override
public void handleRequest() {
//上网的具体实现,找一个转接头
super.request();
}
}
NetToUsb
package com.kuang.adapter;
//按1口转换器的抽象实现~
public interface NetToUsb {
//作1川:处理请求,网线=>usb
public void handleRequest();
}
Adapter2
package com.kuang.adapter;
//真正的适配器,需 要连接USB,连接网线~
public class Adapter2 implements NetToUsb {
//组合模式
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleRequest() {
//上网的具体实现,找一个转接头
adaptee.request();//可以上网
}
}
Computer
package com.kuang.adapter;
//客户端关: 想上:网,插不L:网线~
public class Computer {
//我们的电脑需要连接1:转按器才可以1:网
public void net(NetToUsb adapter) {
//.上网的具体实现, 找“个转接义
adapter.handleRequest();
}
public static void main(String[] args) {
/* //电脑,适配器,网线~
Computer computer = new Computer(); //电脑
Adaptee adaptee = new Adaptee(); //网线
Adapter adapter = new Adapter(); //转按器
computer.net(adapter);*/
System.out.println("++++++++++++++++++++++++++++++");
//电脑,适配器,网线~
Computer computer = new Computer(); //电脑
Adaptee adaptee = new Adaptee(); //网线
Adapter2 adapter = new Adapter2(adaptee); //转按器
computer.net(adapter);
}
}
角色分析
原理理解
桥接模式
代码实现
Brand
package com.kuang.bridge;
//品牌
public interface Brand {
void info();
}
Lenovo
package com.kuang.bridge;
//联想品牌
public class Lenovo implements Brand {
@Override
public void info() {
System.out.print("联想");
}
}
Apple
package com.kuang.bridge;
//联想品牌
public class Apple implements Brand {
@Override
public void info() {
System.out.print("苹果");
}
}
Computer
package com.kuang.bridge;
//抽象的电脑类型类
public abstract class Computer {
//组合,品牌~
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info() {
brand.info();//自带品牌
}
}
class Desktop extends Computer {
public Desktop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.print("台式机");
}
}
class Laptop extends Computer {
public Laptop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.print("笔记本");
}
}
Test
package com.kuang.bridge;
public class Test {
public static void main(String[] args) {
//苹果管记本
Computer computer = new Laptop(new Apple());
computer.info();
System.out.println();
//联想台式机
Computer computer2 = new Desktop(new Lenovo());
computer2.info();
}
}
运行结果
苹果笔记本
联想台式机
原理理解
优劣势分析
原理再理解
代理模式
往期博客
为什么要学习代理模式,因为AOP的底层机制就是动态代理!【AOP&SpringMVC】
代理模式:
-
静态代理
-
动态代理
学习aop之前 , 我们要先了解一下代理模式!
静态代理
静态代理
静态代理角色分析
-
抽象角色 : 一般使用接口或者抽象类来实现
-
真实角色 : 被代理的角色
-
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作 .
-
客户 : 使用代理角色来进行一些操作 .
步骤
1.接口
2.真实角色
3.代理角色
4.客户端访问代理角色
代码实现
Rent.java
即抽象角色
//抽象角色:租房
public interface Rent {
public void rent();
}
Host.java
即真实角色
//真实角色: 房东,房东要出租房子
public class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
Proxy.java
即代理角色
//代理角色:中介
public class Proxy implements Rent {
private Host host;
public Proxy() { }
public Proxy(Host host) {
this.host = host;
}
//租房
public void rent(){
seeHouse();
host.rent();
fare();
}
//看房
public void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
Client.java
即客户
//客户类,一般客户都会去找代理!
public class Client {
public static void main(String[] args) {
//房东要租房
Host host = new Host();
//中介帮助房东
Proxy proxy = new Proxy(host);
//你去找中介!
proxy.rent();
}
}
分析:在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。
静态代理的好处:
-
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
-
公共的业务由代理来完成 . 实现了业务的分工 ,
-
公共业务发生扩展时变得更加集中和方便 .
缺点 :
- 类多了 , 多了代理类 , 工作量变大了 . 开发效率降低 .
我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !
静态代理再理解
静态代理再理解
同学们练习完毕后,我们再来举一个例子,巩固大家的学习!
练习步骤:
1、创建一个抽象角色,比如咋们平时做的用户业务,抽象起来就是增删改查!
//抽象角色:增删改查业务
public interface UserService {
void add();
void delete();
void update();
void query();
}
2、我们需要一个真实对象来完成这些增删改查操作
//真实对象,完成增删改查操作的人
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("增加了一个用户");
}
public void delete() {
System.out.println("删除了一个用户");
}
public void update() {
System.out.println("更新了一个用户");
}
public void query() {
System.out.println("查询了一个用户");
}
}
3、需求来了,现在我们需要增加一个日志功能,怎么实现!
-
思路1 :在实现类上增加代码 【麻烦!】
-
思路2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!
4、设置一个代理类来处理日志!代理角色
//代理角色,在这里面增加日志的实现
public class UserServiceProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public void add() {
log("add");
userService.add();
}
public void delete() {
log("delete");
userService.delete();
}
public void update() {
log("update");
userService.update();
}
public void query() {
log("query");
userService.query();
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
5、测试访问类:
public class Client {
public static void main(String[] args) {
//真实业务
UserServiceImpl userService = new UserServiceImpl();
//代理类
UserServiceProxy proxy = new UserServiceProxy();
//使用代理类实现日志功能!
proxy.setUserService(userService);
proxy.add();
}
}
OK,到了现在代理模式大家应该都没有什么问题了,重点大家需要理解其中的思想;
我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是AOP中最核心的思想
聊聊AOP:纵向开发,横向开发
动态代理
动态代理
-
动态代理的角色和静态代理的一样 .
-
动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的
-
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
-
基于接口的动态代理----JDK动态代理
-
基于类的动态代理–cglib
-
现在用的比较多的是 javasist 来生成动态代理 . 百度一下javasist
-
我们这里使用JDK的原生代码来实现,其余的道理都是一样的!、
-
JDK的动态代理需要了解两个类
核心 : InvocationHandler
和 Proxy
, 打开JDK帮助文档看看
【InvocationHandler
:调用处理程序】
Object invoke(Object proxy, 方法 method, Object[] args);
//参数
//proxy - 调用该方法的代理实例
//method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
//args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
【Proxy : 代理】
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
代码实现
抽象角色和真实角色和之前的一样!
Rent.java
即抽象角色
//抽象角色:租房
public interface Rent {
public void rent();
}
Host.java
即真实角色
//真实角色: 房东,房东要出租房子
public class Host implements Rent{
public void rent() {
System.out.println("房屋出租");
}
}
ProxyInvocationHandler.java
即代理角色
public class ProxyInvocationHandler implements InvocationHandler {
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
rent.getClass().getInterfaces(),this);
}
// proxy : 代理类 method : 代理类的调用处理程序的方法对象.
// 处理代理实例上的方法调用并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//核心:本质利用反射实现!
Object result = method.invoke(rent, args);
fare();
return result;
}
//看房
public void seeHouse(){
System.out.println("带房客看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
}
Client.java
//租客
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理实例的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setRent(host); //将真实角色放置进去!
Rent proxy = (Rent)pih.getProxy(); //动态生成对应的代理类!
proxy.rent();
}
}
核心:一个动态代理 , 一般代理某一类业务 , 一个动态代理可以代理多个类,代理的是接口!
深化理解
深化理解
我们来使用动态代理实现代理我们后面写的UserService!
我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为Object即可!
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}
// proxy : 代理类
// method : 代理类的调用处理程序的方法对象.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
public void log(String methodName){
System.out.println("执行了"+methodName+"方法");
}
}
测试!
public class Test {
public static void main(String[] args) {
//真实对象
UserServiceImpl userService = new UserServiceImpl();
//代理对象的调用处理程序
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService); //设置要代理的对象
UserService proxy = (UserService)pih.getProxy(); //动态生成代理类!
proxy.delete();
}
}
测试,增删改查,查看结果!
更加直观的举例
动态代理:在内存中形成代理类
实现步骤:
1.代理对象和真实对象实现相同的接口
2.代理对象= Proxy . newInstance();
3.使用代理对象调用方法。
4.增强方法
抽象角色(抽象方法)
package cn.itcast.web.proxy;
public interface SaleComputer {
public String sale(double money);
public void show();
}
真实角色
package cn.itcast.web.proxy;
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
return "花了"+money+"买了一台电脑";
}
@Override
public void show(){
System.out.println("展示电脑。。。");
}
}
动态代理
package cn.itcast.web.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
//创建真实对象
Lenovo lenovo = new Lenovo();
/*
三个参数。
1.类加载器:真实对象. getClass().getClassLoader()
2.接口数组:真实对象. getClass().getInterfaces()
3.处理器: new InvocationHandler()
*/
//动态增强创建的真实对象lenovo
SaleComputer o = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/*
代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
参数:
1. proxy:代理对象
2. method:代理对象调用的方法,被封装为的对象
3. args:代理对象调用的方法时,传递的实际参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理方法"+method.getName()+"被执行");
//System.out.println(method.getName() + "-->参数" + args[0]);
//增强参数
if (method.getName().equals("sale")) {
double money = (double) args[0];
Object invoke = method.invoke(lenovo, money);
//增强返回值
return invoke+"送电脑包";
}else {
Object invoke = method.invoke(lenovo, args);
return invoke;
}
}
});
String sale = o.sale(8000d);
System.out.println(sale);
System.out.println("***********************");
o.show();
}
}
动态代理的好处
动态代理的好处
-
静态代理有的它都有,静态代理没有的,它也有!
-
可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .
-
公共的业务由代理来完成 . 实现了业务的分工 ,
-
公共业务发生扩展时变得更加集中和方便 .
-
一个动态代理 , 一般代理某一类业务
-
一个动态代理可以代理多个类,代理的是接口!
彻底玩转单例模式
饿汉式 DCL懒汉式,深究!
饿汉式
饿汉式
package com.kuang.single;
// 饿汉式单例
public class Hungry {
// 可能会浪费空间
private byte[] data1 = new byte[1024*1024];
private byte[] data2 = new byte[1024*1024];
private byte[] data3 = new byte[1024*1024];
private byte[] data4 = new byte[1024*1024];
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
DCL 懒汉式
DCL 懒汉式
package com.kuang.single;
import com.sun.corba.se.impl.orbutil.CorbaResourceUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
// 懒汉式单例
// 道高一尺,魔高一丈!
public class LazyMan {
private static boolean qinjiang = false;
private LazyMan(){
synchronized (LazyMan.class){
if (qinjiang == false){
qinjiang = true;
}else {
throw new RuntimeException("不要试图使用反射破坏异常");
}
}
}
private volatile static LazyMan lazyMan;
// 双重检测锁模式的 懒汉式单例 DCL懒汉式
public static LazyMan getInstance(){
if (lazyMan==null){
synchronized (LazyMan.class){
if (lazyMan==null){
lazyMan = new LazyMan(); // 不是一个原子性操作
/**
* 1.分配内存空间
* 2.执行构造方法,初始化对象
* 3.把这个对象指向这个空间
* 123
*132A
*B //此时LazyMan还没有完成构造
*/
}
}
}
return lazyMan;
}
// 反射!
public static void main(String[] args) throws Exception {
// LazyMan instance = LazyMan.getInstance();
Field qinjiang = LazyMan.class.getDeclaredField("qinjiang");
qinjiang.setAccessible(true);
Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);
declaredConstructor.setAccessible(true);
LazyMan instance = declaredConstructor.newInstance();
qinjiang.set(instance,false);
LazyMan instance2 = declaredConstructor.newInstance();
System.out.println(instance);
System.out.println(instance2);
}
}
/**
* 1. 分配内存空间
* 2、执行构造方法,初始化对象
* 3、把这个对象指向这个空间
*
* 123
* 132 A
* B // 此时lazyMan还没有完成构造
*/
静态内部类
静态内部类
package com.kuang.single;
// 静态内部类
public class Holder {
private Holder(){
}
public static Holder getInstace(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
单例不安全,反射
枚举
枚举
package com.kuang.single;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
// enum 是一个什么? 本身也是一个Class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class Test{
public static void main(String[] args) throws NoSuchMethodException,
IllegalAccessException, InvocationTargetException, InstantiationException {
EnumSingle instance1 = EnumSingle.INSTANCE;
Constructor<EnumSingle> declaredConstructor =
EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance2 = declaredConstructor.newInstance();
// NoSuchMethodException: com.kuang.single.EnumSingle.<init>()
System.out.println(instance1);
System.out.println(instance2);
}
}
枚举类型的最终反编译源码:
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: EnumSingle.java
package com.kuang.single;
public final class EnumSingle extends Enum
{
public static EnumSingle[] values()
{
return (EnumSingle[])$VALUES.clone();
}
public static EnumSingle valueOf(String name)
{
return (EnumSingle)Enum.valueOf(com/kuang/single/EnumSingle, name);
}
private EnumSingle(String s, int i)
{
super(s, i);
}
public EnumSingle getInstance()
{
return INSTANCE;
}
public static final EnumSingle INSTANCE;
private static final EnumSingle $VALUES[];
static
{
INSTANCE = new EnumSingle("INSTANCE", 0);
$VALUES = (new EnumSingle[] {
INSTANCE
});
}
}