学习资料:狂神说Java
设计模式

一. 创建型模式

省去new,帮我们更好的创建对象

1. 单例模式

  • 构造函数私有
  • 不要new对象啦

饿汉式,DCL懒汉式,深究!

饿汉式:

//饿汉式单例
public class Hungry {//问题,可能浪费空间private byte[] data1 = new byte[1 * 1024 * 1024];private byte[] data2 = new byte[1 * 1024 * 1024];private byte[] data3 = new byte[1 * 1024 * 1024];private byte[] data4 = new byte[1 * 1024 * 1024];//构造函数私有:别人就不能new了private Hungry() {}//一上来就new,加载private final static Hungry HUNGRY = new Hungry();public static Hungry getInstance() {return HUNGRY;}
}

问题:很可能会浪费内存

懒汉式:(双重检测锁模式懒汉式单例)

//懒汉式单例
public class LazyMan {private volatile static LazyMan lazyMan;//避免指令重排//构造器私有private LazyMan() {System.out.println(Thread.currentThread().getName() + "Ok");}//双重检测锁模式的懒汉式单例,DCL懒汉式public static LazyMan getInstance() {if (lazyMan == null) {synchronized (LazyMan.class) {if (lazyMan == null) {lazyMan = new LazyMan();// 不是原子性操作/*** 1. 分配内存空间* 2. 执行构造方法,初始化对象* 3. 把这个对象指向这个空间** 可能指令重排的现象* 原来:123* 如果:132 A线程没问题*           B //此时lazyMan还没有完成构造*/}}}return lazyMan;}//单线程ok,多线程并发下public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {LazyMan.getInstance();}).start();}}
}

静态内部类:

package 设计模式.单例模式;
//静态内部类
//不安全有反射这个东西
public class Holder {private Holder(){}public static Holder getInstance(){return InnerClass.HOLDER;}public static class InnerClass{private static final Holder HOLDER = new Holder();}
}

反射破坏单例:

public static void main(String[] args) throws Exception {LazyMan lazyMan1 = new LazyMan();Constructor<LazyMan> constructor = LazyMan.class.getDeclaredConstructor(null);constructor.setAccessible(true);//无视privateLazyMan lazyMan2 = constructor.newInstance();System.out.println(lazyMan1==lazyMan2);}
}

解决:最终解决,源码中枚举类型不能被反射破坏


测试枚举:

import java.lang.reflect.Constructor;//枚举 是什么?本身也是一个类
public enum EnumSingle {INSTANCE;//默认单例public EnumSingle getInstance(){return INSTANCE;}
}class Test{public static void main(String[] args) throws Exception {EnumSingle enumSingle1 = EnumSingle.INSTANCE;Constructor<EnumSingle> constructor = EnumSingle.class.getDeclaredConstructor(null);constructor.setAccessible(true);EnumSingle enumSingle2 = constructor.newInstance();System.out.println(enumSingle1==enumSingle2);}
}

编译器骗了我们枚举没有无参构造

枚举没有无参构造的,有有参构造(String,int)

2. 工厂模式

  • 实现了创建者和调用者分离

  • 分类

    • 简单工厂模式

      • 用来生产同一等级结构中的任意产品(对于增加新的产品,需要覆盖已有代码)
      • 车接口
      package factory.simple;public interface Car {public void name();
      }
      
      • 各种车
      public class TesLa implements Car {@Overridepublic void name() {System.out.println("特斯拉!");}
      }
      ---------------------------------------
      package edu.xalead.factory.simple;public class WuLin implements Car {@Overridepublic void name() {System.out.println("五菱宏光!");}
      }
      
      • 买车的消费者
      package factory.simple;
      //弊端: 增加一个新的产品,需要修改原来的代码(为了满足开闭原则)
      public class Consumer {public static void main(String[] args) {//之前
      //        Car wuLin = new WuLin();
      //        Car tesLa = new TesLa();//使用工厂创建Car wuLin = CarFactory.getCar("五菱");Car tesLa = CarFactory.getCar("特斯拉");wuLin.name();tesLa.name();}
      }
      
      • 创建一个车工厂: 但如果来一个别的车的话需要修改代码
      package factory.simple;public class CarFactory {public static Car getCar(String car){if(car.equals("五菱")){return new WuLin();}else if (car.equals("特斯拉")){return new TesLa();}elsereturn null;}
      }
      
    • 工厂方法模式

      • 用来生产同一等级中的固定产品(支持增加任意产品)
      • 车接口
      package edu.xalead.factory.method;public interface Car {public void name();
      }
      
      • 车接口工厂,谁来生产车不用管
      package edu.xalead.factory.method;public interface CarFactory {Car getCar();
      }
      
      • 各种车
      package edu.xalead.factory.method;public class TesLa implements Car {@Overridepublic void name() {System.out.println("特斯拉!");}
      }对应车接口:
      package edu.xalead.factory.method;public class TesLaFactory implements CarFactory {@Overridepublic Car getCar() {return new TesLa();}
      }
      --------------------------------------------------------
      package edu.xalead.factory.method;public class WuLin implements Car {@Overridepublic void name() {System.out.println("五菱宏光!");}
      }
      对应车接口:
      package edu.xalead.factory.method;public class WuLinFactory implements CarFactory {@Overridepublic Car getCar() {return new WuLin();}
      }
      
      • 消费者
      package edu.xalead.factory.method;public class Consumer {public static void main(String[] args) {Car car1 = new WuLinFactory().getCar();Car car2 = new TesLaFactory().getCar();car1.name();car2.name();}
      }
      
    • 抽象工厂模式

      • 围绕一个超级工厂创建其它工厂。该超级工厂又被称为其它工厂的工厂


- 大工厂

 package edu.xalead.factory.abstract1;//抽象产品工厂public interface IProductFactory {//生产手机IphoneProduct getPhone();//生产路由器IRouterProduct getRouter();}
- 华为工厂,总工厂已经确定需要生产哪些产品了
 package edu.xalead.factory.abstract1;public class HuaweiFactory implements IProductFactory {@Overridepublic IphoneProduct getPhone() {return new HuaweiPhone();}@Overridepublic IRouterProduct getRouter() {return new HuaweiRouter();}}
- 华为产品
 //手机package edu.xalead.factory.abstract1;public class HuaweiPhone implements IphoneProduct {@Overridepublic void start() {System.out.println("开启华为手机");}@Overridepublic void shutdown() {System.out.println("关闭华为手机");}@Overridepublic void callup() {System.out.println("华为手机打电话");}@Overridepublic void sendSMS() {System.out.println("华为发短信");}}-----------------------------------------------//路由器package edu.xalead.factory.abstract1;public class HuaweiRouter implements IRouterProduct {@Overridepublic void start() {System.out.println("启动华为路由器");}@Overridepublic void shutdown() {System.out.println("关闭华为路由器");}@Overridepublic void setting() {System.out.println("设置华为路由器");}}
- 小米工厂
 package edu.xalead.factory.abstract1;public class XiaomiFactory implements IProductFactory {@Overridepublic IphoneProduct getPhone() {return new XiaomiPhone();}@Overridepublic IRouterProduct getRouter() {return new XiaomiRouter();}}
- 小米产品
 //手机package edu.xalead.factory.abstract1;public class XiaomiPhone implements IphoneProduct {@Overridepublic void start() {System.out.println("开启小米手机");}@Overridepublic void shutdown() {System.out.println("关闭小米手机");}@Overridepublic void callup() {System.out.println("小米打电话");}@Overridepublic void sendSMS() {System.out.println("小米发短信");}}//路由器package edu.xalead.factory.abstract1;public class XiaomiRouter implements IRouterProduct {@Overridepublic void start() {System.out.println("启动小米路由器");}@Overridepublic void shutdown() {System.out.println("关闭小米路由器");}@Overridepublic void setting() {System.out.println("设置小米路由器");}}
 //产品接口package edu.xalead.factory.abstract1;//手机接口public interface IphoneProduct {void start();void shutdown();void callup();void sendSMS();}------------------------------------package edu.xalead.factory.abstract1;//路由器接口public interface IRouterProduct {void start();void shutdown();void setting();}
- 客户
 package edu.xalead.factory.abstract1;public class Client {public static void main(String[] args) {//小米工厂XiaomiFactory xiaomiFactory = new XiaomiFactory();//手机IphoneProduct phone = xiaomiFactory.getPhone();phone.start();phone.callup();//路由器IRouterProduct router = xiaomiFactory.getRouter();router.start();router.setting();HuaweiFactory huaweiFactory = new HuaweiFactory();IphoneProduct phone1 = huaweiFactory.getPhone();phone.start();phone.callup();IRouterProduct router1 = huaweiFactory.getRouter();router1.start();router1.setting();}}
  • 满足oop七大原则

    • 开闭原则:一个软件实体应该对扩展开放,对修改关闭
    • 依赖倒转原则:要针对接口编程,不要针对实现编程
    • 迪米特法则:只与你直接的朋友通信,而避免和陌生人通信
  • 核心本质

    • 实例化对象不使用new,用工厂方法代替
    • 将选择实现类,创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
  • 应用场景

    • JDK中Calendar的getInstance方法
    • JDBC中的Connection对象的获取
    • Spring中IOC容器创建管理bean对象
    • 反射中Class对象的newInstance方法

3. 建造者模式

提供了一种创建对象的最佳方式

  • 定义: 将一个复杂对象的构建与它的表示分离,使得同样的构建 过程可以创建不同的表示。

  • 主要作用:在用户不知道对象的建造过程和细节的情况下就可以直接创建复杂的对象。

  • 用户只需要给出指定复杂对象的类型和内容,建造者模式负责按顺序创建复杂对象(把内部的建造过程和细节隐藏起来)

  • 例子:

    • 工厂(建造者模式) :负责制造汽车(组装过程和细节在工厂内)
    • 汽车购买者(用户) :你只需要说出你需要的型号(对象的类型和内容),然后直接购买就可以使用.(不需要知道汽车是怎么组装的(车轮、 车门、发动机、方向盘等等) )
  • 代码实现

    建房子的例子,必须要有个指挥

    • 抽象的Builder

      package edu.xalead.builder.demo1;
      //抽象的建造者:方法
      public abstract class Builder {abstract void builderA();//地基abstract void builderB();//钢筋框架abstract void builderC();//铺电线abstract void builderD();//粉刷// 经过ABCD四步,就完工了abstract Product getProduct();
      }
      
    • 产品

      package edu.xalead.builder.demo1;import lombok.Data;
      import lombok.ToString;//产品:房子
      @Data
      @ToString
      public class Product {private String buildA;private String buildB;private String buildC;private String buildD;
      }
      
    • 具体Builder

      package edu.xalead.builder.demo1;
      //具体的建造者:工人
      public class Worker extends Builder {private Product product;//工人创建产品public Worker(){product = new Product();}@Overridevoid builderA() {product.setBuildA("地基");System.out.println("地基");}@Overridevoid builderB() {product.setBuildB("钢筋框架");System.out.println("钢筋框架");}@Overridevoid builderC() {product.setBuildC("铺设电线");System.out.println("铺设电线");}@Overridevoid builderD() {product.setBuildD("粉刷");System.out.println("粉刷");}@OverrideProduct getProduct() {return product;}}
      
    • 指挥

      package edu.xalead.builder.demo1;
      //指挥:核心,指挥一个工程的构建
      public class Director {//指挥工人按照顺序建造房子public Product build(Builder builder){builder.builderA();builder.builderB();builder.builderC();builder.builderD();return builder.getProduct();}
      }
      
    • 测试:

      package edu.xalead.builder.demo1;public class TestBuild {public static void main(String[] args) {//指挥Director director = new Director();//指挥具体的工人Product build = director.build(new Worker());System.out.println(build.toString());}
      }
      

    买东西,我们用户可以选除了套餐外的其它搭配

    • 抽象Builder

      package edu.xalead.builder.demo2;//建造者
      public abstract class Builder {abstract Builder builderA(String msg);//汉堡abstract Builder builderB(String msg);//可乐abstract Builder builderC(String msg);//薯条abstract Builder builderD(String msg);//甜品// 经过ABCD四步,套餐完成abstract Product getProduct();
      }
      
    • 产品

      package edu.xalead.builder.demo2;import lombok.Data;
      import lombok.ToString;//产品:套餐
      @Data
      @ToString
      public class Product {private String BuildA = "汉堡";private String BuildB = "可乐";private String BuildC = "薯条";private String BuildD = "甜品";
      }
      
    • 具体Builder

      package edu.xalead.builder.demo2;
      //具体的建造者
      public class Worker extends Builder {private Product product;public Worker(){product = new Product();}@OverrideBuilder builderA(String msg) {product.setBuildA(msg);return this;}@OverrideBuilder builderB(String msg) {product.setBuildB(msg);return this;}@OverrideBuilder builderC(String msg) {product.setBuildC(msg);return this;}@OverrideBuilder builderD(String msg) {product.setBuildD(msg);return this;}@OverrideProduct getProduct() {return product;}
      }
      
    • 测试

      package edu.xalead.builder.demo2;public class Test {public static void main(String[] args) {//服务员Worker worker = new Worker();//链式编程:在原来基础上可以自由组合了,如果不组合就用默认的Product product = worker.builderA("全家桶").builderB("雪碧").builderC("薯片").getProduct();System.out.println(product.toString());}
      }
      
  • 优点:

    • 产品的建造和表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。
    • 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
    • 具体的建造者类之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的
      代码,符合“开闭原则"。
  • 缺点:

    • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似;如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制
    • 如果产品的内部变化复杂, 可能会导致需要定 义很多具体建造者类来实现这种变化, 导致系统变得很庞大。
  • 应用场景:

    • 需要生成的产品对象有复 杂的内部结构,这些产品对象具备共性;
    • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。
    • 适合于- -个具有较多的零件(属性)的产品(对象)的创建过程。
  • 建造者与抽象工厂模式的比较:

    • 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
    • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象, 返回-个完整的对象。
    • 如果将抽象工厂模式看成汽车配件生产工厂,生产-一个产品族的产品,那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车!

4. 原型模式

主要是克隆:

clone()

  1. 实现cloneable接口
    clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法

  2. 重写clone()方法

    clone() 方法并不是 Cloneable 接口的方法,而是 Object 的一个 protected 方法。Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,就会抛出 CloneNotSupportedException。

分浅拷贝和深拷贝:

  • 浅拷贝:

    拷贝对象和原始对象的引用类型引用同一个对象

  • 深拷贝:

    拷贝对象和原始对象的引用类型引用不同对象。


浅拷贝例子:

package edu.xalead.prototype.demo1;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.util.Date;/*** 1. 实现一个接口* 2. 重写一个方法*/
//Video
@Data
@NoArgsConstructor
@ToString
public class Video implements Cloneable{private String name;private Date createTime;@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public Video(String name, Date createTime) {this.name = name;this.createTime = createTime;}
}

客户端:

package edu.xalead.prototype.demo1;import java.util.Date;// 客户端: 克隆
public class Client {// 浅拷贝,公用同一个数据datepublic static void main(String[] args) throws CloneNotSupportedException {//原型对象Date date = new Date();Video v1 = new Video("网站",date);System.out.println("v1=>"+v1);System.out.println("v1=>hash:"+v1.hashCode());//v1 克隆出 v2Video v2 = (Video) v1.clone();System.out.println("v2=>"+v2);System.out.println("v2=>hash:"+v2.hashCode());v2.setName("克隆网站");System.out.println(v2);}
}

深拷贝例子:

package edu.xalead.prototype.demo2;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;import java.util.Date;/*** 1. 实现一个接口* 2. 重写一个方法*/
//Video
@Data
@NoArgsConstructor
@ToString
public class Video implements Cloneable{private String name;private Date createTime;@Overrideprotected Object clone() throws CloneNotSupportedException {Object clone = super.clone();//实现深克隆Video v = (Video) clone;//将这个对象的属性也克隆一份v.createTime = (Date) this.createTime.clone();return v;}public Video(String name, Date createTime) {this.name = name;this.createTime = createTime;}
}

客户端:

package edu.xalead.prototype.demo2;import java.util.Date;
// 客户端: 克隆/*** Spring Bean :单例模式,原型模式创建** 原型模式 + 工厂 ==》 new <=> 原型模式*/
public class Client {// 深拷贝public static void main(String[] args) throws CloneNotSupportedException {//原型对象Date date = new Date();Video v1 = new Video("网站",date);Video v2 = (Video) v1.clone();System.out.println("v1=>"+v1);System.out.println("v2=>"+v2);//date.setTime(152645789);System.out.println("--------------------------");System.out.println("v1=>"+v1);System.out.println("v2=>"+v2);}
}

二. 结构型模式

作用: 从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题

1. 适配器模式

  • 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能- -起工作的
    那些类可以在一起工作!

  • 角色分析

    • 目标接口:客户所期待的接口,目标可以是具体的或抽象的类,也可以是接口。
    • 需要适配的类:需要适配的类或适配者类。
    • 适配器:通过包装一一个需要适配的对象, 把原接口转换成目标对象!
  • 对象适配器优点
    ◆一个对象适配器可以把多个不同的适配者适配到同-一个目标
    ◆可以适配一-个适配者的子类,由于适配器和适配者之间是关联关系,根据“里氏代换原则”,适配者
    的子类也可通过该适配器进行适配。

  • 类适配器缺点

    • 对于Java、 C#等不支持多重类继承的语言,一次最多只能适配一个适配者类,不能同时适配多个适配者;

    • 在Java、 C#等语言中,类适配器模式中的目标抽象类只能为接口,不能为类,其使用有一定的局限性。

  • 适用场景

    • 系统需要使用一-些现有的类,而这些类的接口(如方法名)不符合系统的需要,甚至没有这些类的源代码。
    • 想创建一一个可以重复使用的类,用于与- -些彼此之间没有太大关联的一些类,包括- -些可能在将来引进的类一起作。
  • 代码

当我们需要用网线上网的时候,但电脑是薄的无法插网线

网线:

package edu.xalead.adapter;
//要被适配的类:比如网线
public class Adaptered {public void request(){System.out.println("网线上网");}
}

适配器:

//抽象接口
package edu.xalead.adapter;
//转换器的抽象实现
public interface NetToUsb {//作用处理请求,把网线插到适配器上适配器插到usb接口void handleRequest();
}
------------------------------------
package edu.xalead.adapter;/*** 1. 继承(类适配器,单继承)*/
//真正的适配器,需要连接USB,连接网线
public class Adapter extends Adaptered implements NetToUsb {@Overridepublic void handleRequest() {super.request();//可以上网了}
}
-------------------------------------
package edu.xalead.adapter;/*** 2. 组合(对象适配器,常用)*/
//真正的适配器,需要连接USB,连接网线
public class Adapter2 implements NetToUsb {private Adaptered adaptered;//网线组合进来了public Adapter2(Adaptered adaptered) {this.adaptered = adaptered;}@Overridepublic void handleRequest() {adaptered.request();//可以上网了}
}

电脑连网:

package edu.xalead.adapter;
//客户端类:想上网,插不上网线
public class Computer {public void net(NetToUsb adapter){//上网但插不上网线,找一个转接头adapter.handleRequest();}public static void main(String[] args) {//电脑,适配器,网线Computer computer = new Computer();Adaptered adaptered = new Adaptered();//网线
//        Adapter adapter = new Adapter();Adapter2 adapter = new Adapter2(adaptered);//computer.net(adapter);}
}

2. 桥接模式

有两个以上变化的维度:比如联想,苹果,戴尔,他们都有台式机,笔记本,平板

  • 好处分析:

    • 桥接模式偶尔类似于多继承方案,但是多继承方案违背了类的单一职责原则,复用性比较差,类的个数也非常多,桥接模式是比多继承方案更好的解决方法。极大的减少了子类的个数,从而降低管理和维护的成本

    • 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。符合开闭原则,就像一座桥,可以把两个变化的维度连接起来!

  • 劣势分析:

    • 桥接模式的引入会增加系 统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
    • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一 定的局限性。
  • 最佳实践:

    • 如果一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建
      立静态的继承联系,通过桥接模式可以使它们在抽象层建立-个关联关系。抽象化角色和实现化角色
      可以以继承的方式独立扩展而互不影响,在程序运行时可以动态将-个抽象化子类的对象和一一个实现
      化子类的对象进行组合,即系统需要对抽象化角色和实现化角色进行动态耦合。
    • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
    • 虽然在系统中使用继承是没有问题的,但是由于抽象化角色和具体化角色需要独立变化,设计要求需
      要独立管理这两者。对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,
      桥接模式尤为适用。
  • 场景:

    • Java语言通过Java虚拟机实现了平台的无关性。

    • AWT中的Peer架构

    • JDBC驱动程序也是桥接模式的应用之一。

思考?桥接模式+适配器模式

3. 代理模式

SpringAOP底层

分类:

  • 静态代理
  • 动态代理

3.1 静态代理

角色分析:

  • 抽象角色:一般会用接口活着抽象类解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色的同时,还可以做一些附属的操作
  • 客户:访问代理对象的人!

上代码:

  • 抽象角色:

    package edu.xalead.proxy.demo1;
    //抽象的接口,出租房子这件事
    public interface Rent {void rent();
    }
    
  • 真实角色:

    package edu.xalead.proxy.demo1;
    //房东,真实角色
    public class Hoster implements Rent {@Overridepublic void rent() {System.out.println("本房东有房子出租");}
    }
    
  • 代理角色:

    package edu.xalead.proxy.demo1;public class ProxyRent implements Rent {private Hoster hoster;public ProxyRent(Hoster hoster) {this.hoster = hoster;}@Overridepublic void rent() {seeHouse();hoster.rent();hetong();}//还可以做一些其它的事public void seeHouse(){System.out.println("中介带你看房子");}public void hetong(){System.out.println("签合同");}
    }
    
  • 客户:

    package edu.xalead.proxy.demo1;
    //客户来租房了
    public class Client {public static void main(String[] args) {//房东出租房子Hoster hoster = new Hoster();//代理角色,中介帮房东租房子,但是呢,代理角色还有些附属操作ProxyRent proxyRent = new ProxyRent(hoster);//你看不到房东,直接找中介租房子proxyRent.rent();}
    }
    

代理模式的好处: .

  • 可以使真实角色的操作更加纯粹!不用去关注- -些公共的业务

  • 公共也就就交给代理角色!实现了业务的分工!

  • 公共业务发生扩展的时候,方便集中管理!

缺点:

  • 一个真实角色就会产生-个代理角色;代码量会翻倍.开发效率会变低~
3.2 动态代理
  • 动态代理与静态代理角色一样
  • 动态代理是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口的—JDK动态代理
    • 基于类的----cglib
    • Java字节码实现----javassist

我们在这里使用基于接口的动态代理

我们在这里了解两个类:

  • Proxy: 生成动态代理实例
  • InovactionHandler: 调用处理程序并返回一个结果

上代码:

  • 抽象角色:
package edu.xalead.proxy.demo4active;public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void del() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("更新了一个用户");}@Overridepublic void query() {System.out.println("查询出一个用户");}
}
  • 真实角色:
package edu.xalead.proxy.demo4active;public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("增加了一个用户");}@Overridepublic void del() {System.out.println("删除了一个用户");}@Overridepublic void update() {System.out.println("更新了一个用户");}@Overridepublic void query() {System.out.println("查询出一个用户");}
}
  • 代理角色:动态生成的,通用的,代理的是接口
package edu.xalead.proxy.demo4active;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;//这个类,自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {//被代理的接口private Object target;public void setTarget(Object target) {this.target = target;}//Proxy,生成代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}//InvocationHandler@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//动态代理的本质就是利用反射实现Object result = method.invoke(target, args);return result;}
}
  • 客户端:
package edu.xalead.proxy.demo4active;public class Client {public static void main(String[] args) {//真实角色UserServiceImpl userService = new UserServiceImpl();//生成代理角色ProxyInvocationHandler invocationHandler = new ProxyInvocationHandler();invocationHandler.setTarget(userService);UserService proxy = (UserService)invocationHandler.getProxy();//动态生成代理类proxy.add();}
}

好处,一个动态代理类,可以代理多个类,只要是实现了同一个接口即可。

后续会继续更新的,
欢迎访问我的个人博客交流:http://www.ayjup.cn

深入浅出了解几种简单设计模式相关推荐

  1. js observer 添加_简单了解4种JS设计模式

    阅读本文约需要5分钟 大家好,我是你们的导师,我每天都会在这里给大家分享一些干货内容(当然了,周末也要允许老师休息一下哈).上次老师跟大家分享了15款有用前端开发的ST插件的知识,今天跟大家分享下4种 ...

  2. 深入浅出Java 23种设计模式,最全PDF版本终于开放下载了!!(文末有福利)

    写在前面 在「 冰河技术 」微信公众号中[设计模式专题]更新完毕已有一段时间了.不少小伙伴在我微信上留言说:冰河,你能不能把[设计模式专题]的文章汇总成PDF文档呢?一直没有时间整理,最近在公众号后台 ...

  3. 16种JavaScript设计模式(中)

    简介 上文中介绍了学习设计模式前需要了解的一些基础概念和js的基础模式-原型模式,没看过的同学可以点这里,本章将介绍以下几种模式 单例模式 策略模式 代理模式 迭代器模式 发布订阅模式 命令模式 组合 ...

  4. 大话PHP设计模式:类自动载入、PSR-0规范、链式操作、11种面向对象设计模式实现和使用、OOP的基本原则和自动加载配置...

    一.类自动载入 SPL函数 (standard php librarys) 类自动载入,尽管 __autoload() 函数也能自动加载类和接口,但更建议使用 spl_autoload_registe ...

  5. 23种经典设计模式都有哪些,如何分类?Java设计模式相关面试

    23种经典设计模式都有哪些,如何分类? 23种经典设计模式都有哪些,如何分类? java常用的设计模式?说明工厂模式 Java 中的23 种设计模式: Factory(工厂模式), Builder(建 ...

  6. 深入浅出JMS(三)--ActiveMQ简单的HelloWorld实例

    第一篇博文深入浅出JMS(一)–JMS基本概念,我们介绍了JMS的两种消息模型:点对点和发布订阅模型,以及消息被消费的两个方式:同步和异步,JMS编程模型的对象,最后说了JMS的优点. 第二篇博文深入 ...

  7. 23种开发设计模式总结,追求高内聚低耦合的编程思想。

    目录 一.概述 二.7个设计原则 1.单一职责原则 ( SRP ) 2.开闭原则 ( OCP ) 3.里氏替换原则 ( LSP ) 4.依赖倒置原则 ( DIP ) 5.接口隔离原则 ( ISP ) ...

  8. Java简单设计模式

    Java简单设计模式 V哥官网:http://www.vgxit.com 本博客对应视频教程:http://www.vgxit.com/course/21 1,为什么要学习这门课 我们很多人都喜欢金庸 ...

  9. 细谈八种架构设计模式及其优缺点概述

    作者:风平浪静如马 一.什么是架构 我想这个问题,十个人回答得有十一个答案,因为另外的那一个是大家妥协的结果.哈哈,我理解,架构就是骨架,如下图所示: 人类的身体的支撑是主要由骨架来承担的,然后是其上 ...

最新文章

  1. Android 圆角矩形ProgressBar
  2. C语言程序可以没有main函数
  3. 零基础学Python(第十二章 列表【list】)
  4. android 打包jar包
  5. android.view.InflateException: Binary XML file line #34: Error inflating class
  6. 【剑指offer】面试题30:包含min函数的栈(Java)
  7. 《全数据时代的炼金师》全书语言生动、易懂
  8. 至诚学院MATLAB第四次,MATLAB 第二次实验课课堂作业(4学时)
  9. 利用神经网络内部表征可视化class-specific image regions区域
  10. .net 委托 +lamda表达式
  11. 《Web前端工程师修炼之道(原书第4版)》——互联网与Web
  12. NSURLConnect 的简单实用(iOS8淘汰)
  13. java删除未引用的库_利用Proguard移除无用代码以及碰到的坑
  14. 2019年8月9日 下午6:06:12 BD5613F5-0BE7-44DF-B231-CCC87
  15. [Halcon测量] 测量助手详解
  16. 解决linux下syslog文件过大
  17. 应用程序初始化(0xc0000034)失败
  18. oracle重建inventory,Oracle中Inventory目录作用以及如何重建此目录-Oracle
  19. 深入理解Linux电源管理(0.2)
  20. [bzoj1233]干草堆tower

热门文章

  1. 【云开发】全网最详细壁纸小程序教程+源码
  2. html论坛发帖案例
  3. Nacos注册中心和服务消费方式
  4. csgo举报机器人怎么安排_求一个CSGO的举报和点赞用的机器人
  5. “工业互联网+安全生产”,提升工业企业安全水平
  6. Unity中UI的LookAt效果实现
  7. 【NVMe2.0b 9】控制器初始化过程
  8. YOLOv3学习——锚框和候选区域
  9. 移动游戏防作弊攻防战
  10. 总结 62 种在深度学习中的数据增强方式