首页
统计
关于
Search
1
Sealos3.0离线部署K8s集群
1,338 阅读
2
类的加载
888 阅读
3
Spring Cloud OAuth2.0
880 阅读
4
SpringBoot自动装配原理
769 阅读
5
集合不安全问题
670 阅读
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Canvas
React
Linux
容器
Docker
Containerd
Podman
Kubernetes
Python
FastApi
OpenCV
数据分析
牛牛生活
登录
Search
标签搜索
Java
CSS
mysql
RabbitMQ
JavaScript
Redis
OpenCV
JVM
Mybatis-Plus
Camunda
多线程
CSS3
Python
React
Canvas
Spring Cloud
注解和反射
Activiti
工作流
SpringBoot
蘇阿細
累计撰写
464
篇文章
累计收到
4
条评论
首页
栏目
笔记
Java
多线程
注解和反射
JVM
JUC
设计模式
Mybatis
Spring
SpringMVC
SpringBoot
MyBatis-Plus
Elastic Search
微服务
Dubbo
Zookeeper
SpringCloud
Nacos
Sentinel
数据库
MySQL
Oracle
PostgreSQL
Redis
MongoDB
工作流
Activiti7
Camunda
消息队列
RabbitMQ
前端
HTML5
CSS
CSS3
JavaScript
jQuery
Vue2
Vue3
Canvas
React
Linux
容器
Docker
Containerd
Podman
Kubernetes
Python
FastApi
OpenCV
数据分析
牛牛生活
页面
统计
关于
搜索到
464
篇与
的结果
2022-09-07
结构型模式-组合模式
(1)概述组合模式又称为部分整体模式,是用于把一组相似的对象当作一个单一的对象,该模式依据树形结构来组合对象,用来表示部分以及整体层次(2)结构抽象根节点:定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性树枝节点:定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成树结构叶子节点:其下再无分支,是系统层次遍历的最小单位(3)案例以树形菜单为例:抽象根节点public abstract class MenuComponent { protected String name; protected int level; /** * 添加菜单 * * @param menuComponent */ public void add(MenuComponent menuComponent) { throw new UnsupportedOperationException(); } /** * 移除菜单 * * @param menuComponent */ public void remove(MenuComponent menuComponent) { throw new UnsupportedOperationException(); } /** * 查询子菜单 * * @param index * @return */ public MenuComponent getChild(int index) { throw new UnsupportedOperationException(); } /** * 查询菜单或菜单项的名称 * * @return */ public String getName() { return name; } /** * 打印菜单(包含子菜单和子菜单项) */ public abstract void print(); }树枝节点public class Menu extends MenuComponent { private List<MenuComponent> menuComponentList = new ArrayList<>(); public Menu(String name, int level) { this.name = name; this.level = level; } @Override public void add(MenuComponent menuComponent) { menuComponentList.add(menuComponent); } @Override public void remove(MenuComponent menuComponent) { menuComponentList.remove(menuComponent); } @Override public MenuComponent getChild(int index) { return menuComponentList.get(index); } @Override public void print() { for (int i = 0; i < level; i++) { System.out.print(" "); } //打印菜单名称 System.out.println(name); //打印子菜单/子菜单项名称 for (MenuComponent menuComponent : menuComponentList) { menuComponent.print(); } } } public class MenuItem extends MenuComponent { public MenuItem(String name, int level) { this.name = name; this.level = level; } @Override public void print() { for (int i = 0; i < level; i++) { System.out.print(" "); } //打印菜单项名称 System.out.println(name); } }测试public class Client { public static void main(String[] args) { //创建菜单 MenuComponent menue1 = new Menu("菜单一", 2); menue1.add(new MenuItem("1", 3)); menue1.add(new MenuItem("2", 3)); menue1.add(new MenuItem("3", 3)); MenuComponent menue2 = new Menu("菜单二", 2); menue2.add(new MenuItem("1", 3)); menue2.add(new MenuItem("2", 3)); menue2.add(new MenuItem("3", 3)); MenuComponent menue3 = new Menu("菜单三", 2); menue3.add(new MenuItem("1", 3)); menue3.add(new MenuItem("2", 3)); menue3.add(new MenuItem("3", 3)); MenuComponent menue4 = new Menu("菜单四", 2); menue4.add(new MenuItem("1", 3)); menue4.add(new MenuItem("2", 3)); menue4.add(new MenuItem("3", 3)); //将二级菜单添加到一级菜单中 MenuComponent component = new Menu("根菜单", 1); component.add(menue1); component.add(menue2); component.add(menue3); component.add(menue4); //打印菜单 component.print(); } }(4)分类透明组合模式在该模式中,抽象根节点角色声明了所有用于管理成员对象的方法,以此确保所有的构建类都有相同的接口,即标准组合模式该模式不够安全,因为叶子对象和容器对象有着本质上的区别,叶子对象不可能有下级节点(即不包含成员对象)因此提供的 add()、remove()方法是没有意义的,在运行时调用由于未提供相应的错误处理代码而出错安全组合模式该模式中的抽象根节点角色未提供任何管理成员对象的方法,而是在树枝节点类中声明并实现这些方法,它的缺点是不够透明,因为叶子对象和容器对象具有不同的方法,容器对象中用于管理成员对象的方法没有在抽象根节点中定义,客户端不能实现相应的抽象编程,必须区别对待叶子对象和容器对象(5)优缺点可以清楚定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,便于对整个层次结构的管理客户端可以一致的使用一个组合结构或其中的单个对象,无需关心处理的是单个对象还是整个组合结构新增/删除节点符合开闭原则通过叶子节点和树枝节点的递归组合,可以形成复杂的树形结构,但整个管理的过程并不复杂(6)使用场景多用于需要使用树形结构的场景
2022年09月07日
76 阅读
0 评论
0 点赞
2022-09-07
结构型模式-外观模式
(1)概述外观模式又称门面模式,是一种通过为多个复杂的子系统提供一个一致的接口,而使这些子系统更容易被访问,外部应用程序无需关心内部子系统的具体细节,它是“迪米特法则”的典型应用(2)结构外观角色:为多个子系统对外提供一个共同的接口子系统角色:实现系统的部分功能,客户可以通过外观角色访问它(3)案例以智能音箱控制家电为例外观角色public class SmartApplicationFacade { private Light light; private TV tv; private AirCondition airCondition; public SmartApplicationFacade() { light = new Light(); tv = new TV(); airCondition = new AirCondition(); } public void say(String message) { if (message.contains("开")) { on(); } else if (message.contains("关")) { off(); } else { System.out.println("主人,你在说什么?"); } } private void on() { //一键打开 light.on(); tv.on(); airCondition.on(); } private void off() { light.off(); tv.off(); airCondition.off(); } }子系统角色public class TV { public void on() { System.out.println("开电视"); } public void off() { System.out.println("关电视"); } } public class Light { public void on() { System.out.println("开灯"); } public void off() { System.out.println("关灯"); } } public class AirCondition { public void on() { System.out.println("开空调"); } public void off() { System.out.println("关空调"); } }测试public class Client { public static void main(String[] args) { SmartApplicationFacade smartApplicationFacade = new SmartApplicationFacade(); smartApplicationFacade.say("开灯"); System.out.println("=========================="); smartApplicationFacade.say("关电视"); } }(4)优缺点降低了子系统与客户端之间的耦合度对客户屏蔽了子系统组件不符合开闭原则(5)使用场景对分层系统构建时,使用外观模式定义每层的入口点可以简化子系统之间的依赖关系当一个复杂系统的子系统很多时,外观模式可以提供简单的接口供外界访问当客户端与多个子系统之间存在很大的联系时,引入外观模式可将他们分离从而提高子系统的独立性和可移植性
2022年09月07日
91 阅读
0 评论
0 点赞
2022-09-05
结构型模式-桥接模式
(1)概述将抽象与实现分离,使它们可以独立变化,用组合关系代替继承关系来实现,从而降低抽象和实现这两个可变维度的耦合度(2)结构抽象化角色:定义抽象类,并包含一个对实现化角色的引用扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法实现化角色:定义实现化角色的接口(也可以是抽象类),供扩展抽象化角色调用具体实现化角色:给出实现化角色接口的具体实现(3)案例以视频播放器为例(可以在不同操作系统上播放多种格式的视频文件)实现化角色public interface VideoFile { /** * 视频解码 * * @param fileName */ void decode(String fileName); }具体实现化角色public class MkvFile implements VideoFile { @Override public void decode(String fileName) { System.out.println("播放mkv视频文件:" + fileName); } } public class Mp4File implements VideoFile { @Override public void decode(String fileName) { System.out.println("播放mp4视频文件:" + fileName); } }抽象化角色public abstract class OperationSystem { //声明VideoFile变量 protected VideoFile videoFile; public OperationSystem(VideoFile videoFile) { this.videoFile = videoFile; } /** * 播放视频 * * @param fileName */ public abstract void play(String fileName); }扩展抽象化角色public class Windows extends OperationSystem { public Windows(VideoFile videoFile) { super(videoFile); } @Override public void play(String fileName) { videoFile.decode(fileName); } } public class Mac extends OperationSystem { public Mac(VideoFile videoFile) { super(videoFile); } @Override public void play(String fileName) { videoFile.decode(fileName); } }(4)优缺点提高了系统的可扩展性,在两个变化的维度中任意扩展一个维度,都不需要修改原有系统实现细节对客户透明(5)使用场景当一个类存在两个独立变化的维度,且这两个维度都需要扩展时当一个系统不希望使用继承或因多层次继承导致类爆炸时当一个系统需要在构建的抽象化角色和具体化角色之间增加更多的灵活性时(避免在两个层次之间建立静态的继承联系,可通过桥接模式(聚合引用方式)使它们在抽象层建立一个关联关系)
2022年09月05日
80 阅读
0 评论
0 点赞
2022-09-05
结构型模式-装饰者模式
(1)概述在不改变现有对象结构的情况下,动态的给该对象增加额外的职责或功能(2)结构抽象构建角色:定义一个抽象接口以规范准备接收附加责任的对象具体构建角色:实现抽象构建,通过装饰角色为其添加一些职责抽象装饰角色:继承或实现抽象构建,并包含具体构建的实例,可以通过其子类扩展具体构建的功能具体装饰角色:实现抽象装饰的相关方法,并给具体构建对象添加附加的职责或功能(3)案例以快餐店为例:抽象构建角色public abstract class FastFood { private float price; private String desc; public FastFood() { } public FastFood(float price, String desc) { this.price = price; this.desc = desc; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } /** * 计算价格 * * @return */ public abstract float cost(); }具体构建角色public class FriedNoodles extends FastFood { public FriedNoodles() { super(8, "炒面"); } @Override public float cost() { return super.getPrice(); } } public class FriedRice extends FastFood { public FriedRice() { super(10, "炒饭"); } @Override public float cost() { return super.getPrice(); } }抽象装饰角色public abstract class Garnish extends FastFood { private FastFood fastFood; public Garnish(FastFood fastFood, float price, String desc) { super(price, desc); this.fastFood = fastFood; } public FastFood getFastFood() { return fastFood; } public void setFastFood(FastFood fastFood) { this.fastFood = fastFood; } }具体装饰角色public class Egg extends Garnish { public Egg(FastFood fastFood) { super(fastFood, 1, "鸡蛋"); } @Override public float cost() { //价格:鸡蛋 + 快餐的价格 return super.getPrice() + super.getFastFood().cost(); } @Override public String getDesc() { //描述:鸡蛋 + 具体的快餐 return super.getDesc() + super.getFastFood().getDesc(); } } public class Bacon extends Garnish { public Bacon(FastFood fastFood) { super(fastFood, 2, "培根"); } @Override public float cost() { //价格:培根 + 快餐的价格 return super.getPrice() + super.getFastFood().cost(); } @Override public String getDesc() { //描述:培根 + 具体的快餐 return super.getDesc() + super.getFastFood().getDesc(); } }测试public class Client { public static void main(String[] args) { //炒饭 FastFood food = new FriedRice(); System.out.println(food.getDesc() + " " + food.cost() + "元"); //再加一个鸡蛋 food = new Egg(food); //System.out.println(food.getDesc() + " " + food.cost() + "元"); //加培根 food = new Bacon(food); System.out.println(food.getDesc() + " " + food.cost() + "元"); } }(4)优缺点装饰者模式可以带来比继承更加灵活的扩展功能,可以通过组合不同的装饰者对象来获取具有不同行为状态的多样化的结果遵循开闭原则,继承是静态的附加责任,装饰者则是动态的附加责任装饰类和被装饰类可以各自独立发展,不会产生耦合,装饰者模式是继承的一个替代模式,可以动态扩展一个实现类的功能(5)使用场景当不能采用继承的方式对系统进行扩充或采用继承不利于系统扩展和维护时类中存在大量独立的扩展,使用继承可能会造成类爆炸时被 final 修饰的类在不影响其他对象的情况下,以动态、透明的方式给单个对象添加功能或职责当对象的功能要求动态添加,动态移除时(6)静态代理与装饰者模式的区别相同点:都要实现与目标类相同的业务接口在两个类中都要声明目标对象都可以在不修改目标对象的前提下进行功能增强不同点:目的不同:装饰者增强目标对象静态代理保护和隐藏目标对象获取目标对象构建的地方不同装饰者中的目标对象由外界传递(通过构造方法或set赋值)静态代理的目标对象在代理类内部创建,以此来完成隐藏和保护
2022年09月05日
64 阅读
0 评论
0 点赞
2022-09-04
结构型模式-适配器模式
(1)概述将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类能一起工作,分为类适配器模式(耦合度高)和对象适配器模式(2)结构目标接口:当前系统业务所期待的接口(抽象类或接口)适配者类:它是被访问和适配的现存组件库中的组件接口适配器类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者(3)类适配器模式实现方式:定义一个适配器类来实现当前系统的业务接口(即目标接口),同时又继承现有组件库中已经存在的组件(即适配者类)以读卡器为例:目标接口public interface SDCard { /** * 读数据 * * @return */ String readSD(); /** * 写数据 * * @param msg */ void writeSD(String msg); }具体的SD卡类public class SDCardImpl implements SDCard { @Override public String readSD() { return "Read data from SDCard: Hello World"; } @Override public void writeSD(String msg) { System.out.println("Write data to SDCard:" + msg); } }public class Computer { public String readSD(SDCard sdCard) { if (sdCard == null) { throw new NullPointerException("SDCard can not be null"); } return sdCard.readSD(); } }适配者类接口public interface TFCard { /** * 读数据 * * @return */ String readTF(); /** * 写数据 * * @param msg */ void writeTF(String msg); }适配者类public class TFCardImpl implements TFCard { @Override public String readTF() { return "Read data from TFCard: Hello World"; } @Override public void writeTF(String msg) { System.out.println("Write data to TFCard:" + msg); } }适配器类public class SDAdapterTF extends TFCardImpl implements SDCard { @Override public String readSD() { System.out.println("Adapter read from TFCard"); return super.readTF(); } @Override public void writeSD(String msg) { System.out.println("Adapter write to TFCard"); super.writeTF(msg); } }测试public class Client { public static void main(String[] args) { //计算机 Computer computer = new Computer(); //读取SDCard中的数据 String msg = computer.readSD(new SDCardImpl()); System.out.println(msg); System.out.println("===================================="); //使用该电脑读取TFCard中的数据 //定义适配器类 String msg1 = computer.readSD(new SDAdapterTF()); System.out.println(msg1); } }类适配器模式违背了合成复用原则,在客户类有一个明确的接口规范的情况下可用,反之不可用(4)对象适配器模式实现方式:采用将现有组件库中已实现的组件引入适配器类中,该类同时实现当前系统的业务接口读卡器案例改进:目标接口public interface SDCard { /** * 读数据 * * @return */ String readSD(); /** * 写数据 * * @param msg */ void writeSD(String msg); }具体的SD卡类public class SDCardImpl implements SDCard { @Override public String readSD() { return "Read data from SDCard: Hello World"; } @Override public void writeSD(String msg) { System.out.println("Write data to SDCard:" + msg); } }public class Computer { public String readSD(SDCard sdCard) { if (sdCard == null) { throw new NullPointerException("SDCard can not be null"); } return sdCard.readSD(); } }适配者类接口public interface TFCard { /** * 读数据 * * @return */ String readTF(); /** * 写数据 * * @param msg */ void writeTF(String msg); }适配者类public class TFCardImpl implements TFCard { @Override public String readTF() { return "Read data from TFCard: Hello World"; } @Override public void writeTF(String msg) { System.out.println("Write data to TFCard:" + msg); } }适配器类public class SDAdapterTF implements SDCard { //适配者类 private TFCard tfCard; public SDAdapterTF(TFCard tfCard) { this.tfCard = tfCard; } @Override public String readSD() { System.out.println("Adapter read from TFCard"); return tfCard.readTF(); } @Override public void writeSD(String msg) { System.out.println("Adapter write to TFCard"); tfCard.writeTF(msg); } }测试public class Client { public static void main(String[] args) { //计算机 Computer computer = new Computer(); //读取SDCard中的数据 String msg = computer.readSD(new SDCardImpl()); System.out.println(msg); System.out.println("===================================="); //使用该电脑读取TFCard中的数据 String msg1 = computer.readSD(new SDAdapterTF(new TFCardImpl())); System.out.println(msg1); } }对象适配器模式解决了类适配器模式中存在的问题;同时还有接口适配器模式,当不希望实现一个接口中的所有方法时,可以定义一个 Adapter 抽象类,实现目标接口中的所有方法,适配器类再继承该抽象类,根据需要选择所需的方法(5)应用场景原系统存在满足新系统功能需求的类,但存在接口不一致的问题时使用第三方提供的组件,但所需组件接口与自己接口定义不同的时候
2022年09月04日
59 阅读
0 评论
0 点赞
2022-09-04
结构型模式-代理模式
结构型模式描述如何将类或对象按某种布局组合成更大的结构,分为类结构型模式和对象结构型模式,前者采用继承来组织接口和类,后者采用组合或聚合来组合对象分为:代理模式、适配器模式、装饰者模式、桥接模式、外观模式、组合模式、享元模式1. 代理模式(1)概述由于某些原因需要给某对象提供一个代理以控制对该对象的访问,这时,访问对象不适合或不能直接引用目标对象,代理对象作为访问对象与目标对象之间的中介Java中的代理按照类生成时机的不同分为静态代理和动态代理,静态代理 代理类在编译时生成,动态代理 代理类在运行时动态生成(JDK动态代理、CGLib动态代理)(2)结构抽象主题类:通过接口或抽象类声明真实主题和代理对象实现的业务方法真实主题类:实现抽象主题中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象代理类:提供与真实主题相同的接口,其内部含有对真实主题的引用,它可以访问、控制以及扩展真实主题的功能(3)静态代理以火车站卖票为例抽象主题类public interface SellTickets { /** * 卖票 */ void sell(); }真实主题类public class TrainStation implements SellTickets { @Override public void sell() { System.out.println("火车站卖票"); } }代理类public class ProxyPoint implements SellTickets { /** * 聚合火车站对象 */ private TrainStation trainStation = new TrainStation(); @Override public void sell() { System.out.println("代售点收取5元手续费"); trainStation.sell(); } }测试public class Client { public static void main(String[] args) { //创建代售点 ProxyPoint proxyPoint = new ProxyPoint(); //顾客从代售点买票 proxyPoint.sell(); } }(4)JDk动态代理抽象主题类public interface SellTickets { /** * 卖票 */ void sell(); }真实主题类public class TrainStation implements SellTickets { @Override public void sell() { System.out.println("火车站卖票"); } }获取代理对象的工厂类public class ProxyFactory { /** * 声明目标对象 */ private final TrainStation trainStation = new TrainStation(); /** * 获取代理对象 * * @return */ public SellTickets getProxyInstance() { //返回代理对象 /** * ClassLoader loader:类加载器(可以通过目标对象获取类加载器) * Class<?>[] interfaces:代理类实现的接口的字节码对象 * InvocationHandler h:代理对象的调用处理程序 */ return (SellTickets) Proxy.newProxyInstance( trainStation.getClass().getClassLoader(), trainStation.getClass().getInterfaces(), new InvocationHandler() { /** * Object proxy:代理对象,和proxyObject是同一个对象,在invoke方法中基本不用 * Method method:对接口中的方法进行封装的method对象 * Object[] args:调用方法的实际参数 * 返回值:方法的返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代售点收取10元手续费(jdk动态代理)"); //执行目标对象的方法 return method.invoke(trainStation, args); } }); } }测试public class Client { public static void main(String[] args) { //获取代理对象 //1.创建代理工厂对象 ProxyFactory proxyFactory = new ProxyFactory(); //2.使用proxyFactory对象的方法获取代理对象 SellTickets proxyObject = proxyFactory.getProxyInstance(); //3.调用卖票的方法 proxyObject.sell(); } }Java中提供了一个动态代理类 Proxy ,即提供了一个创建代理对象的静态方法 newProxyInstance 来获取代理对象使用Arthas (阿尔萨斯)查看代理类的结构:package com.sun.proxy; import com.itheima.proxy.dynamic.jdk.SellTickets; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements SellTickets { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler invocationHandler) { super(invocationHandler); } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("com.itheima.proxy.dynamic.jdk.SellTickets").getMethod("sell", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; } catch (NoSuchMethodException noSuchMethodException) { throw new NoSuchMethodError(noSuchMethodException.getMessage()); } catch (ClassNotFoundException classNotFoundException) { throw new NoClassDefFoundError(classNotFoundException.getMessage()); } } public final boolean equals(Object object) { try { return (Boolean)this.h.invoke(this, m1, new Object[]{object}); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return (Integer)this.h.invoke(this, m0, null); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void sell() { try { this.h.invoke(this, m3, null); return; } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } }从以上类结构可以看出:代理类 $Proxy0 实现了 SellTickets,即真实类和代理类都实现了同样的接口代理类 $Proxy0 将我们提供了的匿名内部类 invocationHandler 传递给了父类动态代理执行流程:在测试类(访问类)中通过代理对象调用 sell() 方法根据多态的特性,执行的代理类是 $Proxy0 中的 sell() 方法代理类 $Proxy0 中的 sell() 方法中又调用了 invocationHandler 接口的子实现类对象的 invoke() 方法invoke 方法通过反射执行了真实对象所属类 TrainStation 中的 sell() 方法(5)CGLib动态代理如果没有定义 SellTickets 接口,只定义了 TrainStation 火车站类,此时无法使用JDK动态代理,因为它要求必须定义接口真实主题类public class TrainStation { public void sell() { System.out.println("火车站卖票"); } }代理对象工厂public class ProxyFactory implements MethodInterceptor { /** * 声明火车站对象 */ private TrainStation trainStation = new TrainStation(); public TrainStation getProxyObject() { //创建Enhancer对象(类似于JDK代理中的Proxy) Enhancer enhancer = new Enhancer(); //设置父类的字节码对象 enhancer.setSuperclass(TrainStation.class); //设置回调函数 enhancer.setCallback(this); //创建代理对象 TrainStation proxyObject = (TrainStation) enhancer.create(); return proxyObject; } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("代售点收取15元手续费(CGLib代理)"); //要调用目标方法的对象 return method.invoke(trainStation, objects); } }测试public class Client { public static void main(String[] args) { //代理工厂 ProxyFactory proxyFactory = new ProxyFactory(); //获取代理对象 TrainStation proxyObject = proxyFactory.getProxyObject(); //调用sell proxyObject.sell(); } }(6)三种代理模式的对比静态代理与动态代理:动态代理将接口中声明的所有方法都转移到调用处理器一个集中的方法中处理(JDK:InvocationHandler.invoke()),在接口方法较多的情况下可以进行灵活的处理;反之静态代理每增加一个方法就需要新增对应的代理类JDK与CGLib动态代理:CGLib 底层采用 ASM 字节码生成框架,使用字节码技术生成代理类,在 JDK1.6 之前比使用 Java反射效率要高,其中需注意:CGLib 不能对声明为 final 类型的类或方法进行代理,因为 CGLib 原理是动态生成被代理类的子类在JDK1.6、1.7、1.8逐步优化之后,在调用次数较少的情况下,其效率高于 CGLib 动态代理,在大量调用的情况下,CGLib 效率优于 JDK1.6、1.7,JDK1.8 时效率高于 CGLib有接口时使用JDK动态代理,没有接口时使用CGLib动态代理(7)优缺点代理模式在客户端与目标对象之间起到中介的作用和保护目标对象的作用可以扩展目标对象的功能将客户端与目标对象分离,降低了耦合度增加了系统的复杂度(8)使用场景远程代理(Remote)本地服务通过网络请求远程服务,将通信部份隐藏起来,只暴露给本地服务一个接口,通过该接口访问远程服务所提供的功能,而不必过多关心通信细节的部分,如:RPC 远程调用防火墙代理在浏览器配置代理功能时,防火墙将请求转发给互联网,收到响应之后再转发给浏览器保护代理控制一个对象的访问,可以给不同的用户提供不同的使用权限
2022年09月04日
137 阅读
0 评论
0 点赞
2022-08-31
创建者模式-建造者模式
(1)概述将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示(2)结构抽象建造者类(Builder):该接口规定要实现复杂对象的哪些部分的创建,并不涉及具体部件的创建具体建造者类(ConcreteBuilder):实现 Builder 接口,完成复杂对象的各个部件的具体创建方法,在构造过程完成后,提供产品的实例产品类(Product):要创建的复杂对象指导者类(Director):调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建(3)实例以生产单车为例public class Bike { private String frame; private String seat; public String getFrame() { return frame; } public void setFrame(String frame) { this.frame = frame; } public String getSeat() { return seat; } public void setSeat(String seat) { this.seat = seat; } }public abstract class Builder { protected Bike bike = new Bike(); /** * 生产车架 */ public abstract void buildFrame(); /** * 生产车座 */ public abstract void buildSeat(); /** * 生产自行车 * * @return */ public abstract Bike createBike(); public Bike construct() { this.buildFrame(); this.buildSeat(); return this.createBike(); } }public class QingJuBuilder extends Builder{ @Override public void buildFrame() { bike.setFrame("青桔牌车架"); } @Override public void buildSeat() { bike.setSeat("青桔牌车座"); } @Override public Bike createBike() { return bike; } } public class MeiTuanBuilder extends Builder { @Override public void buildFrame() { bike.setFrame("美团牌车架"); } @Override public void buildSeat() { bike.setSeat("美团牌车座"); } @Override public Bike createBike() { return bike; } }public class Director { private Builder builder; public Director(Builder builder) { this.builder = builder; } /** * 组装自行车 */ public Bike construct() { builder.buildFrame(); builder.buildSeat(); return builder.createBike(); } }public class Client { public static void main(String[] args) { //指导者 Director director = new Director(new QingJuBuilder()); //指导者指导生产自行车 Bike bike = director.construct(); System.out.println(bike.getFrame()); System.out.println(bike.getSeat()); } }以上实例可以将指导者和抽象建造者结合,这样做可以简化系统复杂度,但不符合单一职责原则public abstract class Builder { protected Bike bike = new Bike(); /** * 生产车架 */ public abstract void buildFrame(); /** * 生产车座 */ public abstract void buildSeat(); /** * 生产自行车 * * @return */ public abstract Bike createBike(); public Bike construct() { this.buildFrame(); this.buildSeat(); return this.createBike(); } }(5)优缺点封装性好,建造者模式可以有效的封装变化,在该过程中,产品类与建造者类相对稳定,将复杂的业务逻辑封装在指导者类中对整体而言有较好的稳定性在建造者模式中,客户端无需关心产品内部组成的细节,将产品本身与创建的过程解耦,使得相同的创建过程可以建造不同的产品可以更细粒度的控制产品的创建过程,即将复杂对象的创建步骤分解在不同的方法中,可以使创建过程更加清晰,也可以更好的控制创建过程易扩展,当有同类产品的新的需求时,新增一个建造者就可以完成,符合开闭原则建造者模式所创建的产品一般来说有较多的相同点,其组成部分相似,如果产品之间差异较大,则不适合使用建造者模式,使其适用范围受限(6)使用场景创建的对象较复杂,有多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的(7)扩展当一个类的构造器需要传入很多参数时,如果创建该类的实例,可能导致代码可读性差和引入新的错误,此时可以使用建造者模式进行重构public class Phone { private String cpu; private String screen; private String memory; private String mainBoard; //私有构造器 private Phone(Builder builder) { this.cpu = builder.cpu; this.screen = builder.screen; this.memory = builder.memory; this.mainBoard = builder.mainBoard; } public static final class Builder { private String cpu; private String screen; private String memory; private String mainBoard; public Builder cpu(String cpu) { this.cpu = cpu; return this; } public Builder screen(String screen) { this.screen = screen; return this; } public Builder memory(String memory) { this.memory = memory; return this; } public Builder mainBoard(String mainBoard) { this.mainBoard = mainBoard; return this; } //使用建造者创建Phone对象 public Phone build() { return new Phone(this); } } @Override public String toString() { return "Phone{" + "cpu='" + cpu + '\'' + ", screen='" + screen + '\'' + ", memory='" + memory + '\'' + ", mainBoard='" + mainBoard + '\'' + '}'; } }
2022年08月31日
96 阅读
0 评论
0 点赞
2022-08-30
创建者模式-原型模式
(1)概述用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象(2)结构抽象原型类:规定了具体原型对象必须实现的 clone() 方法具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象访问类:使用具体原型类中的 clone() 方法来复制新的对象接口类图:(3)实现原型模式的克隆分为浅克隆和深克隆:浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型,仍指向原有属性所指向的对象的内存地址深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,且不再指向原有对象地址Java中 Object 类提供了 clone() 方法来实现浅克隆,Cloneable 接口是上面类图中的抽象原型类,而实现了 Cloneable 接口的子实现类就是具体的原型类。原型类public class Realizetype implements Cloneable { public Realizetype() { System.out.println("具体原型对象创建完成"); } @Override public Realizetype clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功"); return (Realizetype) super.clone(); } }测试public class Client { public static void main(String[] args) throws CloneNotSupportedException { //创建原型对象 Realizetype realizetype = new Realizetype(); //调用clone方法进行对象的克隆 Realizetype realizetype1 = realizetype.clone(); //具体原型对象创建完成 //具体原型复制成功 //false System.out.println(realizetype == realizetype1); } }(4)案例以学校发放“三好学生”奖状为例public class Citation implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public void show() { System.out.println(name + "同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励!"); } @Override public Citation clone() throws CloneNotSupportedException { return (Citation) super.clone(); } }public class CitationTest { public static void main(String[] args) throws CloneNotSupportedException { //创建原型对象 Citation citation = new Citation(); //复制奖状 Citation citation1 = citation.clone(); citation.setName("孙笑川"); citation1.setName("药水哥"); //展示奖状 citation.show(); citation1.show(); } }(5)使用场景对象的创建非常复杂性能和安全要求较高(6)深克隆将奖状案例中的 name 属性修改为 Student 复杂对象属性public class CitationTest { public static void main(String[] args) throws CloneNotSupportedException { //创建原型对象 Citation citation = new Citation(); //创建学生 Student student = new Student(); student.setName("孙笑川"); citation.setStudent(student); //复制奖状 Citation citation1 = citation.clone(); citation1.getStudent().setName("药水哥"); //展示奖状 citation.show(); citation1.show(); //药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励! //药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励! } }存在的问题:使用浅克隆时,克隆出来的对象属性中的 student1 和第一次创建的 student 是同一个对象,此时 setName 方法设置的值是同一个改进:(使用对象流)public class CitationTest { public static void main(String[] args) throws Exception { //创建原型对象 Citation citation = new Citation(); //创建学生 Student student = new Student(); student.setName("孙笑川"); citation.setStudent(student); //创建对象输出流 ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(Paths.get("D:/citation.txt"))); //写对象 oos.writeObject(citation); //释放资源 oos.close(); //创建对象 ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Paths.get("D:/citation.txt"))); Citation citation1 = (Citation) ois.readObject(); ois.close(); citation1.getStudent().setName("药水哥"); citation.show(); citation1.show(); //孙笑川同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励! //药水哥同学,在本学年表现优秀,被评为“三好学生”,特发此状,以资鼓励! } }
2022年08月30日
78 阅读
0 评论
0 点赞
1
...
22
23
24
...
58