设计模式的分类 总体来说设计模式分为三大类:
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
OOP七大原则
开闭原则:对扩展开放,对修改关闭
里氏替换原则:继承必须确保超累所拥有的性质在子类中任然成立(尽量不重写父类的方法)
依赖倒置原则:要面向接口编程,不要面向实现编程
单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性
接口隔离原则:要为各个类创建他们需要的专用接口
迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
合成复用原则:尽量先试用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现
创建型模式
单例模式:
一个类有且仅有一个实例,并且自行实例化向整个系统提供。
应用场景:如:线程池,数据库连接池...!
饿汉式 DCL懒汉式,深究!
饿汉式:
类加载的 初始化阶段就完成了实例的初始化。本质上就是借助了Jvm类加载机制,保证实例的唯一性!
- 加载二进制数据到内存中,生成对应的Class数据结构
- 连接:a.验证,b.准备(给类的静态成员变量赋默认值),c.解析
- 初始化:给类的静态变量赋初值
只有在真正使用对应的类时,才会触发初始化如(当前类是启动类是main函数所在类),直接进行new操作,访问静态属性、访问静态方法,用反射访问类,初始化一个类的子类等!
单例模式首先将构造器私有
// 饿汉式单例
public class Hungry {
//可能会浪费空间
private byte[] date1 = new byte[1024*1024];
private byte[] date2 = new byte[1024*1024];
private byte[] date3 = new byte[1024*1024];
private byte[] date4 = new byte[1024*1024];
//私有构造器
private Hungry(){
}
private final static Hungry HUNGRY = new Hungry();
public static Hungry getInstance(){
return HUNGRY;
}
}
DCL懒汉式
懒汉式
- 懒汉模式:延迟加载,只有在真正使用的时候,才开始实例化!
- 线程安全问题
- double check 加锁优化
- 编译器(JIT),CPU有可能对指令进行指令重排,导致使用到尚未初始化的实例,可以通过添加volatile关键字进行修饰,对于volatile修饰的字段,可以防止指令重排!
//懒汉式单例
//道高一尺,魔高一丈!
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; //volatile 避免指令重排,保证线程间的可见性
//双重检测锁模式的 懒汉式单例 DCL懒汉式
public static LazyMan getInstance() {
if (lazyMan == null) {
synchronized (LazyMan.class){
if (lazyMan == null) {
lazyMan = new 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 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 // 此时还没有完成构造
*/
package singleton;
public class LazySignleton {
public static void main(String[] args) {
/* LazySignleton instance = LazySignleton.getInstance();
LazySignleton instance2 = LazySignleton.getInstance();
System.out.println(instance==instance2);*/
new Thread(()->{
LazySignleton instance = LazySignleton.getInstance();
System.out.println(instance);
}).start();
new Thread(()->{
LazySignleton instance2 = LazySignleton.getInstance();
System.out.println(instance2);
}).start();
}
//1、构造器私有
private LazySignleton(){
}
//2、声明一个静态的属性
public volatile static LazySignleton install;//在这里使用volatile可以避免指令重排!
// 在这里我们多线程下会遇到一些问题,所以我们可以铜鼓加锁解决!
public synchronized static LazySignleton getInstance(){
if (install==null){
/*try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
synchronized (LazySignleton.class){
if (install==null){
install = new LazySignleton();
/*
在字节码层面:JIT、CPU
1、分配空间
2、初始化
3、引用赋值!
*/
}
}
}
return install;
}
}
静态内部类
- 本质上是利用类的加载机制来保证线程安全
- 只有在实际使用的时候,才会触发类的初始化
//静态内部类
public class Holder {
//构造器私有
private Holder(){
}
public static Holder getInstance(){
return InnerClass.HOLDER;
}
public static class InnerClass{
private static final Holder HOLDER = new Holder();
}
}
package singleton;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
public class InnerSignleton {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
/* InnerClassSignleton instance = InnerClassSignleton.getInstance();
InnerClassSignleton instance2 = InnerClassSignleton.getInstance();
System.out.println(instance2==instance);*/
/*new Thread(()->{
InnerClassSignleton instance = InnerClassSignleton.getInstance();
System.out.println(instance);
}).start();
new Thread(()->{
InnerClassSignleton instance2 = InnerClassSignleton.getInstance();
System.out.println(instance2);
}).start();*/
/*Constructor declaredConstructor = InnerClassSignleton.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
InnerClassSignleton innerClassSignleton = declaredConstructor.newInstance();
InnerClassSignleton instance = InnerClassSignleton.getInstance();
System.out.println(innerClassSignleton==instance);*/
InnerClassSignleton instance = InnerClassSignleton.getInstance();
//ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("TestSerilable"));
//oos.writeObject(instance);
//oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("TestSerilable"));
InnerClassSignleton object = ((InnerClassSignleton) ois.readObject());
System.out.println(object==instance);
}
}
//我们可以通过序列化来解决我们单例模式的问题!
class InnerClassSignleton implements Serializable {
static final long serialVersionUID = 42L;
private static class InnerClassHolder{
private static InnerClassSignleton install = new InnerClassSignleton();
}
private InnerClassSignleton(){
// 因为反射可以破坏这种异常,所以我们可以进行一个判断抛出异常!静态内部类、懒汉式可以,但是饿汉式没办法!
if (InnerClassHolder.install!=null){
throw new RuntimeException("不要试图使用反射破坏!");
}
}
public static InnerClassSignleton getInstance(){
return InnerClassHolder.install; //只有在调用返回的时候,才会进行类的初始化!
}
Object readResolve() throws ObjectStreamException{
return InnerClassHolder.install;
}
}
枚举:Enum
单例不安全,反射
//enum 是什么? 本身也是一个class类
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance(){
return INSTANCE;
}
}
class Test{
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
EnumSingle instance = EnumSingle.INSTANCE;
Constructor declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance1 = declaredConstructor.newInstance();
// NoSuchMethodException: com.kuang.single.EnumSingle.()
System.out.println(instance);
System.out.println(instance1);
}
}
package singleton;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
public enum EnumSingleton {
INSTANCE;
public void print(){
System.out.println(this.hashCode());
}
}
// 测试发现枚举天然生成序列化!
class Test{
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
/* EnumSingleton instance = EnumSingleton.INSTANCE;
EnumSingleton instance2 = EnumSingleton.INSTANCE;
System.out.println(instance2==instance);*/
/* Constructor declaredConstructor = EnumSingleton.class.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
EnumSingleton enumSingleton = declaredConstructor.newInstance();
System.out.println(enumSingleton);*/
EnumSingleton instance = EnumSingleton.INSTANCE;
//ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("enumsigleton"));
//oos.writeObject(instance);
//oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("enumsigleton"));
EnumSingleton object = (EnumSingleton) ois.readObject();
System.out.println(instance==object);
}
}
枚举最终反编译:
javap -p 文件名
下载反编译工具将class文件反编译!
工厂模式
简单工厂模式
:简单工厂模式是属于创建型模式,又叫做静态工厂方法模式
例如:(直接看代码)
public interface Car {
void name();
}
定义他的工厂类
//静态工厂模式
//增加一个新的产品,如果不修改代码,做不到!
//开闭原则
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();
}
}
汽车的品牌实现接口
public class Dazhong implements Car{
@Override
public void name() {
System.out.println("大众!");
}
}
public class Tesla implements Car{
@Override
public void name() {
System.out.println("特斯拉!");
}
}
public class WuLing implements Car{
@Override
public void name() {
System.out.println("五菱宏光!");
}
}
消费者买车
public class Consumer {
public static void main(String[] args) {
//接口,所有的实现类!工厂
//Car car = new WuLing();
//Car car2 = new Tesla();
//2.使用工厂类实现
Car car = CarFactory.getCar("五菱");
Car car2 = CarFactory.getCar("特斯拉");
car.name();
car2.name();
}
}
工厂方法模式
:是一种常用的类创建型设计模式,此模式的核心精神是封装类中变化的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。
定义接口
public interface Car {
void name();
}
定义车工厂
//工厂方法模式
public interface CarFactory {
Car getCar();
}
车品牌工厂 :实现车工厂接口
public class MoBaiFactory implements CarFactory{
@Override
public Car getCar() {
return new MoBai();
}
}
public class TeslaFactory implements CarFactory{
@Override
public Car getCar() {
return new Tesla();
}
}
public class WuLingFactory implements CarFactory{
@Override
public Car getCar() {
return new WuLing();
}
}
汽车:实现Car接口
public class MoBai implements Car{
@Override
public void name() {
System.out.println("摩拜单车!");
}
}
public class Tesla implements Car {
@Override
public void name() {
System.out.println("特斯拉!");
}
}
public class WuLing implements Car {
@Override
public void name() {
System.out.println("五菱宏光!");
}
}
消费者可以直接去车工厂提取车,不需要考虑其他
public class Consumer {
public static void main(String[] args) {
Car car = new WuLingFactory().getCar();
Car car2 = new TeslaFactory().getCar();
car.name();
car2.name();
Car car3 = new MoBaiFactory().getCar();
car3.name();
}
}
package factory;
// 简单工厂与方法工厂模式!
public class FactoryMethod {
public static void main(String[] args) {
Application application = new ConcreateProductA();
Product product = application.getObject();
product.method1();
}
}
interface Product{
public void method1();
}
class ProductA implements Product{
@Override
public void method1(){
System.out.println("A method1 start...");
}
}
class ProductB implements Product{
@Override
public void method1(){
System.out.println("B method1 start...");
}
}
class SimpleFactory{
public static Product createProduct(String type){
if (type.equals("A")){
return new ProductA();
}else if(type.equals("B")){
return new ProductB();
}else {
return null;
}
}
}
abstract class Application{
abstract Product createProduct();
Product getObject(){
Product product = createProduct();
return product;
}
}
class ConcreateProductA extends Application{
@Override
Product createProduct() {
return new ProductA();
}
}
class ConcreateProductB extends Application{
@Override
Product createProduct() {
return new ProductB();
}
}
应用场景
- 当你不知道该如何使用对象的确切类型的时候
- 当你希望为库或框架提供扩展的及其内部组件的方法时
抽象工厂模式
:抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。
public interface IProductFactory {
//产品工厂 、生产手机与路由器
//生产手机
IphoneProduct iphoneProduct();
//生产路由器
IRouterProduct routerProduct();
}
//手机产品接口
public interface IphoneProduct {
void start();
void shutdown();
void callup();
void sendSMS();
}
public interface IRouterProduct {
//路由器产品接口
void start();
void shutdown();
void openWifi();
void setting();
}
不同手机工厂:需要实现产品接口,并且重写方法
public class HuaweiFactory implements IProductFactory{
@Override
public IphoneProduct iphoneProduct() {
return new HuaweiIphone();
}
@Override
public IRouterProduct routerProduct() {
return new HuaweiIRouter();
}
}
public class XiaomiFactory implements IProductFactory{
@Override
public IphoneProduct iphoneProduct() {
return new XiaomiPhone();
}
@Override
public IRouterProduct routerProduct() {
return new XiaomiIRouter();
}
}
不同手机实现手机接口
//华为手机
public class HuaweiIphone implements IphoneProduct{
@Override
public void start() {
System.out.println("开启华为手机");
}
@Override
public void shutdown() {
System.out.println("关闭华为手机");
}
@Override
public void callup() {
System.out.println("华为手机打电话");
}
@Override
public void sendSMS() {
System.out.println("华为发短信");
}
}
//小米手机
public class XiaomiPhone implements IphoneProduct{
@Override
public void start() {
System.out.println("开启小米手机");
}
@Override
public void shutdown() {
System.out.println("小米手机关机");
}
@Override
public void callup() {
System.out.println("小米打电话");
}
@Override
public void sendSMS() {
System.out.println("小米发短信");
}
}
//华为路由器
public class HuaweiIRouter 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("华为设置");
}
}
//小米路由器
public class XiaomiIRouter 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("小米设置");
}
}
package factory;
//简单理解:这里的抽象工厂模式,就是我们抽象方法实现的组合!
public class AbstractFactory {
public static void main(String[] args) {
//MysqlDataBaseUtils utils = new MysqlDataBaseUtils();
OracleDataBaseUtils utils = new OracleDataBaseUtils();
Iconnection connection = utils.getConnection();
connection.connect();
IConmand command = utils.getCommand();
command.command();
}
}
//这里我们模拟 :变化 :mysql、oracle...
// connection 、command...
interface Iconnection{
void connect();
}
interface IConmand{
void command();
}
interface IDatabaseUtils{
Iconnection getConnection();
IConmand getCommand();
}
class MysqlConnection implements Iconnection{
@Override
public void connect() {
System.out.println("mysql connection...");
}
}
class MysqlCommand implements IConmand{
@Override
public void command() {
System.out.println("mysql command...");
}
}
class MysqlDataBaseUtils implements IDatabaseUtils{
@Override
public Iconnection getConnection() {
return new MysqlConnection();
}
@Override
public IConmand getCommand() {
return new MysqlCommand();
}
}
class OracleConnection implements Iconnection{
@Override
public void connect() {
System.out.println("oracle connection...");
}
}
class OracleCommand implements IConmand{
@Override
public void command() {
System.out.println("oracle command...");
}
}
class OracleDataBaseUtils implements IDatabaseUtils{
@Override
public Iconnection getConnection() {
return new OracleConnection();
}
@Override
public IConmand getCommand() {
return new OracleCommand();
}
}
建造者模式
( Builder ):建造者模式是设计模式的一种,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
例:工地建房子
//抽象的建造者:方法
public abstract class Builder {
//步骤:A->B->C->D
abstract void buildA();//地基
abstract void buildB();//钢筋工程
abstract void buildC();//铺电线
abstract void buildD();//粉刷
//完工:得到产品
abstract Product getProduct();
}
//产品:房子
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) {
this.buildA = buildA;
}
public String getBuildB() {
return buildB;
}
public void setBuildB(String buildB) {
this.buildB = buildB;
}
public String getBuildC() {
return buildC;
}
public void setBuildC(String buildC) {
this.buildC = buildC;
}
public String getBuildD() {
return buildD;
}
public void setBuildD(String buildD) {
this.buildD = buildD;
}
@Override
public String toString() {
return "Product{" +
"buildA='" + buildA + '\'' +
", buildB='" + buildB + '\'' +
", buildC='" + buildC + '\'' +
", buildD='" + buildD + '\'' +
'}';
}
}
定义一个工人类
public class Worker extends Builder{
private Product product;
public Worker() {
product = new Product();
}
@Override
void buildA() {
product.setBuildA("地基");
System.out.println("地基");
}
@Override
void buildB() {
product.setBuildB("钢筋工程");
System.out.println("钢筋工程");
}
@Override
void buildC() {
product.setBuildC("铺电线");
System.out.println("铺电线");
}
@Override
void buildD() {
product.setBuildD("粉刷");
System.out.println("粉刷");
}
@Override
Product getProduct() {
return product;
}
}
定义指挥者:负责指挥工人
//指挥:核心。负责指挥构建一个工程,工程如何构建,由他指挥
public class Director {
public Product build(Builder builder){
//指挥工人按照顺序建房子
builder.buildA();
builder.buildB();
builder.buildC();
builder.buildD();
return builder.getProduct();
}
}
测试:
public class Test {
public static void main(String[] args) {
//指挥
Director director = new Director();
//指挥 具体的工人完成 产品
Product build = director.build(new Worker());
System.out.println(build.toString());
}
}
public abstract class Builder {
abstract Builder buildeA(String msg);//汉堡
abstract Builder buildeB(String msg);//可乐
abstract Builder buildeC(String msg);//薯条
abstract Builder buildeD(String msg);//甜点
abstract Product getProduct();
}
套餐
//产品:套餐
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 + '\'' +
'}';
}
}
//具体的建造者
public class Worker extends Builder{
private Product product;
public Worker() {
product = new Product();
}
@Override
Builder buildeA(String msg) {
product.setBuildA(msg);
return this;
}
@Override
Builder buildeB(String msg) {
product.setBuildB(msg);
return this;
}
@Override
Builder buildeC(String msg) {
product.setBuildC(msg);
return this;
}
@Override
Builder buildeD(String msg) {
product.setBuildD(msg);
return this;
}
@Override
Product getProduct() {
return product;
}
}
用户可以自己搭配选择
public class Test {
public static void main(String[] args) {
//服务员
Worker worker = new Worker();
//链式编程 : 在原来的基础上,可以自由组合了,如果不组合,也有默认的套餐
Product product = worker.buildeA("全家桶").buildeB("雪碧")
.getProduct();
System.out.println(product.toString());
}
}
原型模式
:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
复制拷贝: 第一个方案复制的会跟之前的共用一个时间
/*
1.实现一个接口 Cloneable
2.重写一个方法 clone()
*/
//Video
public class Video implements Cloneable{
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 +
'}';
}
}
public class Bilibili {
public static void main(String[] args) throws CloneNotSupportedException {
//原型对象 v1
Date date = new Date();
Video v1 = new Video("狂神说JAVA", date);
System.out.println("v1=>"+v1);
System.out.println("v1=>hash"+v1.hashCode());
//v1 克隆 v2
//Video v2 = new Video("狂神说JAVA", date);
Video v2 = (Video) v1.clone();
System.out.println("v2=>"+v2);
System.out.println("v2=>hash"+v2.hashCode());
}
}
第二个在修改时间的情况下会分隔开
/*
1.实现一个接口 Cloneable
2.重写一个方法 clone()
*/
//Video
public class Video implements Cloneable{
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 obj;
}
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 +
'}';
}
}
//Spring Bean:单例模式,原型模式~
// 原型模式 + 工厂模式 ==> new <==> 原型模式
public class Bilibili {
public static void main(String[] args) throws CloneNotSupportedException {
//原型对象 v1
Date date = new Date();
Video v1 = new Video("狂神说JAVA", date);
Video v2 = (Video) v1.clone();
System.out.println("v1=>"+v1);
System.out.println("v2=>"+v2);
System.out.println("======================");
date.setTime(231321312);
System.out.println("v1=>"+v1);
System.out.println("v2=>"+v2);
/*
//原型对象 v1
Date date = new Date();
Video v1 = new Video("狂神说JAVA", date);
System.out.println("v1=>"+v1);
System.out.println("v1=>hash"+v1.hashCode());
//v1 克隆 v2
//Video v2 = new Video("狂神说JAVA", date);
Video v2 = (Video) v1.clone();
System.out.println("v2=>"+v2);
System.out.println("v2=>hash"+v2.hashCode());
*/
}
}
结构型模式
适配器模式
:是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
//接口转换器的抽象实现
public interface NetToUsb {
//作用:处理请求,网线=>usb
public void handleRequest();
}
//要被适配的类 :网线
public class Adaptee {
public void request(){
System.out.println("连接网线上网");
}
}
//1.继承 (类适配器,单继承)----
//2.组合 (对象适配器,常用)
//真正的适配器~,需要连接USB,连接网线~
public class Adapter extends Adaptee implements NetToUsb{
@Override
public void handleRequest() {
super.request();//可以上网了~
}
}
//1.继承 (类适配器,单继承)
//2.组合 (对象适配器,常用)------
//真正的适配器~,需要连接USB,连接网线~
public class Adapter2 implements NetToUsb{
private Adaptee adaptee;
public Adapter2(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleRequest() {
adaptee.request();//可以上网了~
}
}
//客户端类:想上网,插不上网线~
public class Computer {
//我们的电脑需要连接上转接器才可以上网
public void net(NetToUsb adapter) {
//上网的具体实现~,找一个转接头
adapter.handleRequest();
}
public static void main(String[] args) {
//电脑,网线,适配器~
Computer computer = new Computer();//电脑
Adaptee adaptee = new Adaptee();//网线
Adapter2 adapter = new Adapter2(adaptee);//转接器 (比较完美的实现)
//Adapter adapter = new Adapter();//转接器
computer.net( adapter);
}
}
桥接模式
:是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(interface)模式。
结构图:
//品牌
public interface Brand {
void info();
}
//苹果
public class Apple implements Brand{
@Override
public void info() {
System.out.print("苹果");
}
}
//联想
public class Lenovo implements Brand{
@Override
public void info() {
System.out.print("联想");
}
}
//抽象的电脑类
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.println("台式机");
}
}
class Laptop extends Computer{
public Laptop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("笔记本");
}
}
测试类:
public class Test {
public static void main(String[] args) {
//苹果笔记本
Computer computer = new Laptop(new Apple());
computer.info();
//联想台式机
Computer computer2 = new Desktop(new Lenovo());
computer2.info();
}
}
结构:(同理上面的图)
代理模式
为什么要学习代理模式?这就是SpringAOP的底层! 【SpringAOP 和 SpringMVC】
代理模式的分类:
-
静态代理
-
动态代理
1.静态代理
角色分析:
-
抽象角色:一般会使用接口或者抽象类来解决
-
真是角色:被代理的角色
-
代理角色:代理真实角色,代理真实角色后一般会做一些附属操作
-
客户:访问代理对象的人!
代码步骤:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实角色
//房东
public class Landlord implements Rent{
@Override
public void rent() {
System.out.println("房东要出租房子!");
}
}
3.代理角色
public class Proxy implements Rent{
private Landlord landlord;
public Proxy() {
}
public Proxy(Landlord landlord) {
this.landlord = landlord;
}
@Override
public void rent() {
seeHouse();
landlord.rent();
hetong();
fee();
}
public void seeHouse(){
System.out.println("中介带你看房");
}
public void fee(){
System.out.println("收中介费");
}
public void hetong(){
System.out.println("签租赁合同");
}
}
4.客户端访问代理角色
public class Client {
public static void main(String[] args) {
//房东要出租房子
Landlord landlord = new Landlord();
//代理,中介帮房东出租房子,但是呢?代理角色一般会有一些附属操作
Proxy proxy = new Proxy(landlord);
//你不用面对房东,直接找中介租房子即可!
proxy.rent();
}
}
代理模式的好处:
-
可以使真是角色的操作更加纯粹!不用去关注一些公共的业务
-
公共的业务也就交给代理角色!实现了业务的分工!
-
公共业务发生拓展的时候,方便集中管理!
缺点:
-
一个真是角色就会产生一个代理角色:代码量会翻倍~ 开发效率会变低~
2.加深理解静态代理
代码:
1.接口
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
2.实现类
//真实对象
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("修改了一个用户");
}
@Override
public void query() {
System.out.println("查询了一个用户");
}
//1、改动原有的业务代码,在公司中是大忌!
}
3.代理
public class UserServiceProxy implements UserService{
UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
@Override
public void delete() {
log("delete");
userService.delete();
}
@Override
public void update() {
log("update");
userService.update();
}
@Override
public void query() {
log("query");
userService.query();
}
//日志方法
public void log(String msg){
System.out.println("使用了[Debug]"+msg+"方法");
}
}
4.客户端访问
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
}
}
3.动态代理
-
动态代理和静态代理角色一样
-
动态代理的代理类是动态的,不是我们直接写好的!
-
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
-
基于接口- - - JDK动态代理【我们在这里使用】
-
基于类:cglib
-
Java字节码实现:javasist
-
需要了解两个类:Proxy:代理,InvocationHandler:调用处理程序
动态代理的好处:
-
可以使真是角色的操作更加纯粹!不用去关注一些公共的业务
-
公共的业务也就交给代理角色!实现了业务的分工!
-
公共业务发生拓展的时候,方便集中管理!
-
一个动态代理类代理的是一个接口,一般就是对应的一类业务
-
一个动态代理类可以代理多个类,只要是实现了同一个接口即可!
代码:
1.接口
//租房
public interface Rent {
public void rent();
}
2.真实对象
//房东
public class Landlord implements Rent {
@Override
public void rent() {
System.out.println("房东要出租房子!");
}
}
3.代理
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);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态代理的本质,就是反射机制的实现!
seeHouse();
Object result = method.invoke(rent,args);
return result;
}
public void seeHouse(){
System.out.println("中介带看房子");
}
}
4.客户端访问对象
public class Client {
public static void main(String[] args) {
//真实角色
Landlord landlord = new Landlord();
//代理角色:现在没有
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们要调用的接口对象!
pih.setRent(landlord);
Rent proxy = (Rent) pih.getProxy();//这里的proxy就是动态生成的,我们并没有写!
proxy.rent();
}
}
优化动态代理万能的方法:
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成得到代理类
public Object getProxy(){//最后面的this代表实现的接口 InvocationHandler
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
}
@Override
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 msg){
System.out.println("使用了"+msg+"方法");
}
}
public class Client {
public static void main(String[] args) {
//真实角色
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);//设置要代理的对象
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.query();
}
}