跟着狂神学设计模式(工厂模式,抽象工厂模式,建造者模式,原型模式,适配器模式,桥接模式,静动态代理模式,单例模式 )

跟着狂神学设计模式

设计模式

在这里插入图片描述

什么是设计模式

在这里插入图片描述

学习设计模式意义

在这里插入图片描述

设计模式基本要素

在这里插入图片描述

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的动态代理需要了解两个类

核心 : InvocationHandlerProxy , 打开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
        });
    }
}

其他博客

Java设计模式

https://www.cnblogs.com/yazhouasu/category/1818739.html

  • 15
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值