轻松取消Excel密码的三种简单有效方法
626
2022-05-30
要实现如上的结果,我们这次不用静态代理,而是用JDK动态代理
其实所谓的动态代理,也就是不用写代理类了,而是又JDK底层通过反射在内存中帮你创建好了一个代理类
public class logger implements loggers { /** * JDK动态代理: * 我们无需创建代理类,而是有JDK底层的反射帮我们在内存中自动创建 */ @Override public void writerlogger() { System.out.println("写入日志。。"); } }
public interface loggers { void writerlogger(); }
动态代理:
public class loggerProxyMain { private static logger logger=new logger(); public static void main(String[] args) { /** * public static Object newProxyInstance(ClassLoader loader, * Class>[] interfaces, * InvocationHandler h) */ loggers loggers= (com.design.proxy.dongtaiProxy.loggers) Proxy.newProxyInstance(logger.class.getClassLoader(), logger.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* 第一个参数:被代理的类的对象 第二个参数:方法参数args */ System.out.println("代理开始===="); //如果用代理实例调用方法,将会在这里执行 Object invoke = method.invoke(logger, args);//不返回这个对象的话,代理实例为null System.out.println("代理结束"); return invoke; //返回代理实例,并返回到loggers对象中 } }); //****注意:进入invoke方法是有前提的,就是我们要使用代理实例对象loggers,如果不使用它就不会进入到invoke方法中 //输入logger对象也行,也可以让他进入invoke方法 // System.out.println(loggers); /* 当我们去调用代理的方法时,method.invoke就会监听到,并执行被代理的方法 */ loggers.writerlogger(); } }
装饰器模式
我们可以把装饰器分为主菜和配菜,配菜就是装饰器,而主菜就是被装饰的
公式:创建一个抽象类(作为被装饰者的父类),被装饰者类去继承它,然后创建装饰者抽象类并继承被装饰者的父类,再有装饰者子类去继承装饰者抽象类。
案例:
被装饰者的抽象类,在这里是最高的类
public abstract class breakFast { public abstract int cost(); //价格 }
被装饰者具体类
public class rice extends breakFast { /** * 主食:米饭 */ @Override public int cost() { return 5; } }
public class noodles extends breakFast { /** *主食: 面条 */ @Override public int cost() { return 10; } }
装饰者抽象类:继承与被装饰者的父类
public abstract class decorations extends breakFast{ public abstract int cost(); //装饰者的钱 }
装饰者类
public class coke extends decorations { private breakFast breakFast; private final int COKE_COST=2; //coke的价格 public coke(breakFast breakFast){ this.breakFast=breakFast; } @Override public int cost() { return breakFast.cost()+COKE_COST; } }
public class milk extends decorations { private breakFast breakFast; private final int MILK_COST=3; //milk的价格 public milk(breakFast breakFast){ this.breakFast=breakFast; } @Override public int cost() { return breakFast.cost()+MILK_COST; } }
测试:
public class main { public static void main(String[] args) { rice rice = new rice(); //创建被装饰者对象 milk milk = new milk(rice);//把被装饰者对象放到装饰者的构造方法上去 System.out.println("rice:"+rice.cost()); System.out.println("milk+rice:"+milk.cost()); milk milk1 = new milk(milk); System.out.println("milk*2+rice"+milk1.cost()); } }
适配器模式
适配器模式:就是把原本互不兼容的两样东西或者格式,转换成可以兼容
比如说:家用电压是220v,但是我们手机充电不需要这么大的电压,我们这时候需要电源适配器(充电头),去适配这个电压,把220v适配成(比如:5v,11v等等)
再比如说:有一个方法只能接收int类型数据,但是我们接收到了一个String类型数据,int和String本身就是两个不相同的类型,所以说这个方法是接收不到String类型的,我们可以使用适配器,把String类型转换(适配)成int类型,这样这个方法就可以接收到这个String类型数据了。
公式:适配器类要继承src(原来的类),并实现dest(目标)接口
首先创建适配器类,并运用上面的公式:
public class classAdapter extends srcClass implements destInterface{ /** * 类适配器是有公式的 * 公式:类适配器要继承源类,实现于目标接口 * public class classAdapter extends srcClass implements destInterface * * srcClass:在这里是指家用电压220V * destInterface : 在这里是指我们想适配成多少v的电压,比如手机常用的电压 5v */ @Override public int vivoBattery_5V() { int src = super.getSrc(); int dest=src/44; return dest; } }
源(src)类:
public class srcClass { private final int v=220; //家用电压 //源类生成220v public int getSrc(){ return v; } }
目标接口:
public interface destInterface { int vivoBattery_5V(); //vivo手机想要多少伏的电压 }
测试:
public class Test { public static void main(String[] args) { classAdapter classAdapter = new classAdapter(); int res = classAdapter.vivoBattery_5V(); System.out.println("当前电压:"+res+"v"); } }
为什么会有对象适配器:我们的对象适配器都是在类适配器上优化的,类适配器的缺点是extends(继承),因为Java是单继承的,而我们的对象适配器不过就是把这个extends srcClass 优化成一个对象,通过构造器进行传入,然后通过这个对象进行调用srcClass的方法,而类适配器就是通过super关键字去调用方法。。
public class adapter implements destInterface { private srcClass srcClass; //把之前的类适配器的extends 源类,改成一个对象进行调用 public adapter(srcClass srcClass){ //再通过构造器传入srcClass对象 this.srcClass=srcClass; } @Override public int get10V() { int src = srcClass.getV(); int dest=src/22; return dest; } }
public interface destInterface { int get10V(); }
public class srcClass { private final int v=220; public int getV(){ return v; } }
public class Test { public static void main(String[] args) { adapter adapter = new adapter(new srcClass()); int v = adapter.get10V(); System.out.println(v); } }
为何有接口适配器:我们上面说的两种适配器方式都有一个缺点:就是我们上面两种适配器都需要实现目标接口,当目标接口有多个适配方法时,我们都要对它进行实现,而我们不需要全部实现,只需要实现其中一个即可,我们的接口适配器就是为了解决这个问题的。
没有给接口方法默认实现时:
public interface dest { int adapter_5v(); int adapter_10v(); int adapter_20v(); }
public class adapter implements dest { @Override public int adapter_5v() { return 0; } @Override public int adapter_10v() { return 0; } @Override public int adapter_20v() { return 0; } }
就需要全部进行实现,很复杂
public class srcClass { private final int v=220; //家用电压 //源类生成220v public int getSrc(){ return v; } }
public interface dest { /** * 当接口适配的方法很多,但是我们不需要全部的进行实现,我们可以随便给他一个默认值,用default修饰 * 当我们需要具体实现某个方法时,只需要重写对应的方法即可 */ default int adapter_5v(){ return 0; } default int adapter_10v(){ return 0; } default int adapter_20v(){ return 0; } }
public class adapter implements dest { private srcClass srcClass; public adapter(srcClass srcClass){ this.srcClass=srcClass; } @Override public int adapter_10v() { int src = srcClass.getSrc(); int res=src/22; return res; } }
class main{ public static void main(String[] args) { adapter adapter = new adapter(new srcClass()); int i = adapter.adapter_10v(); System.out.println(i); } }
享元模式
享元模式:“享”是共享 ,“元”是对象 ,享元模式也就是一种利用共享技术对实例对象进行共享,提高实例对象的复用性,和节省资源的开销,减少对象的创建,应用在大量的“”相似“”对象,但是这些对象只有一些不同,我们可以用这个模式。
享元模式如何在定制相似的对象(对对象的数据进行修改):我们可以通过享元模式的简单工厂从HashMap/HashTable中get到,然后再用set方法对它进行定制。
何为相似的对象: 说白了也就是同一个类创建出来的对象就是相似的对象
案例:用户的网站界面属性(网站类型(type)、颜色(color),动态消息(message))
public abstract class website { /** * 总的网站抽象类 */ public abstract void setColor(String color); public abstract void setMessages(List
public class sina extends website { /** * 新浪网站 */ private final String type="新浪"; private String color; private List
public class zhihu extends website { /** * 知乎 */ private final String type="知乎"; private String color; private List
享元工厂(相当于简单工厂的升级版):
这边存在线程安全问题,因为getWebsiteByFactory方法不是原子操作,所以我们多线程环境下一定要加锁
public class simpleFactory { /** * 享元模式是需要简单工厂模式的 */ private Map
测试:
public class main { private static final String[] websites={"新浪","知乎"}; public static void main(String[] args) { simpleFactory simpleFactory = new simpleFactory(); //创建享元模式的简单工厂 website s1 = simpleFactory.getWebsiteByFactory("新浪"); System.out.println(s1); //会创建对象 /** * 享元模式重要作用之一:定制对象 */ s1.setColor("利用享元模式定制对象"); website s2 = simpleFactory.getWebsiteByFactory("新浪"); System.out.println(s2); //不会创建对象,而是从map里面拿 Random random = new Random(); // for (int i = 0; i < 20; i++) { // new Thread(()->{ // website website = simpleFactory.getWebsiteByFactory(websites[random.nextInt(2)]); // System.out.println(website); // // }).start(); // } } }
输出结果:
创建新浪网站对象成功 sina{type='新浪', color='red', messages=[hello713], randomCode='2522'} 在享元模式的简单工厂中已经存在这个网站,所以直接获取到,没有重新创建对象 sina{type='新浪', color='利用享元模式定制对象', messages=[hello713], randomCode='2522'}
只需在getWebsiteByFactory方法上加锁即可
public class simpleFactory { /** * 享元模式是需要简单工厂模式的 */ private Map
组合模式(树型结构)
组合模式的项目应用:实现多级菜单 、文件夹的管理
组合模式我们把它看成一种“树”型结构,固然后面我们在打印这些内容的时候是需要用递归的
因为组合模式是按照树形结构来组合的,所以也有树的特点(比如:叶子节点)
案例:利用组合模式来实现三级菜单。
定义组合模式的菜单组件接口,并定义添加、删除、展示结点方法:
public interface component { /** * 组件接口:所有菜单都要实现这个component(组件)接口 * 组合模式所需方法:添加结点、删除结点、打印菜单 */ //需要给这个添加结点一个默认实现,因为我们的叶子结点不需要添加结点和删除结点这两个方法 default void addNode(component component){ throw new UnsupportedOperationException();//默认抛出不支持操作异常 } default void deleteNode(component component){ throw new UnsupportedOperationException(); } //打印===都需要实现 void showMenu(); }
菜单组件实现类(非叶子结点==第一、二级菜单):
一级菜单:
public class firstMenu implements component { /** * 一级菜单 */ private String name; //菜单名称 private List
二级菜单:
public class secondMenu implements component { /** * 二级菜单 */ private String name; private List
三级菜单:(叶子节点),没有添加、删除结点方法
public class lastMenu implements component { private String name; /** * 最后一个菜单(三级菜单):不能添加和删除,因为它是树的叶子结点 */ public lastMenu(String name){ this.name=name; } @Override public void showMenu() { System.out.println("---------"+this.name); } }
组合模式客户端代码:
public class client { /** * 组合模式客户端 * @param args */ public static void main(String[] args) { //创建一级菜单 component f1=new firstMenu("用户列表"); //创建二级菜单 component s1=new secondMenu("用户信息"); component s2=new secondMenu("用户权限"); component s3=new secondMenu("用户好友"); //创建三级菜单 component l1=new lastMenu("信息修改"); component l2=new lastMenu("信息删除"); component l3=new lastMenu("修改权限"); component l4=new lastMenu("添加好友"); component l5=new lastMenu("删除好友"); component l6=new lastMenu("修改好友信息"); //进行组合 f1.addNode(s1); f1.addNode(s2); f1.addNode(s3); s1.addNode(l1); s1.addNode(l2); s2.addNode(l3); s3.addNode(l4); s3.addNode(l5); s3.addNode(l6); //展示菜单 f1.showMenu(); } }
输出结果:
---用户列表 ------用户信息 ---------信息修改 ---------信息删除 ------用户权限 ---------修改权限 ------用户好友 ---------添加好友 ---------删除好友 ---------修改好友信息
外观模式
为什么会有外观模式?外观模式能解决什么?其实就是把其他对象调用方法封装到外观类上,我们只需要通过调用外观类的方法就可以调用其他类的方法
总结:外观模式(门面模式)说白了就是把多个不同对象(类)的方法归纳到一个门面类(外观类)中,这样省去频繁创建对象,核心就是门面类
使用两种方法实现案例“买水果问题”。。
苹果实体类:
public class apple { /** * 苹果实体类 */ private String id; private String name; public apple(String name){ this.name=name; } public void setId(String id) { this.id = id; } public String getName() { return name; } @Override public String toString() { return "apple{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } }
public class banana { /** * 香蕉实体类 */ private String id; private String name; public banana(String name){ this.name=name; } public void setId(String id) { this.id = id; } public String getName() { return name; } @Override public String toString() { return "banana{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } }
public class orange { /** * 橙子实体类 */ private String id; private String name; public orange(String name){ this.name=name; } public void setId(String id) { this.id = id; } public String getName() { return name; } @Override public String toString() { return "orange{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}'; } }
创建各自的商店:
public class appleStore { /** * 苹果专卖店 */ //买苹果 public apple buyApple(){ apple apple = new apple("苹果"); apple.setId(UUID.randomUUID().toString().replaceAll("-","")); return apple; } }
public class bananaStore { //香蕉实体店 public banana buyBanana(){ banana banana = new banana("香蕉"); banana.setId(UUID.randomUUID().toString().replaceAll("-","")); return banana; } }
public class orangeStore { //橙子实体店 public orange buyOrange(){ orange orange=new orange("橙子"); orange.setId(UUID.randomUUID().toString().replaceAll("-","")); return orange; } }
顾客买水果:
public class client { public static void main(String[] args) { //买苹果 //1.创建苹果店对象 appleStore appleStore = new appleStore(); //2.购买 apple apple = appleStore.buyApple(); //买香蕉 bananaStore bananaStore = new bananaStore(); banana banana = bananaStore.buyBanana(); //买橙子 orangeStore orangeStore = new orangeStore(); orange orange = orangeStore.buyOrange(); System.out.println(apple); System.out.println(banana); System.out.println(orange); } }
====================
总结:可以看出来使用传统方法买水果比较复杂,顾客需要创建各自的商店,再去购买。。。
上面实体类不变,只需要添加一个门面类(外观类)即可
核心(外观类):
public class myFacade { /** * 创建门面类(外观类) */ //这几个变量也可以写成单例,这里暂且不写 private appleStore appleStore; private bananaStore bananaStore; private orangeStore orangeStore; public myFacade(){ //初始化对象 this.appleStore=new appleStore(); this.bananaStore=new bananaStore(); this.orangeStore=new orangeStore(); } /** * 精髓。。。 * 使用外观模式的外观类来归纳方法,把多个类的方法归纳到一个外观类中 * @return */ //创建门面方法(外观方法),购买水果 //买苹果 public apple buyAppleByfacade(){ apple apple = appleStore.buyApple(); apple.setId(UUID.randomUUID().toString().replaceAll("-","")); return apple; } //买香蕉 public banana buyBananaByfacade(){ banana banana = bananaStore.buyBanana(); banana.setId(UUID.randomUUID().toString().replaceAll("-","")); return banana; } //买橙子 public orange buyOrangeByfacade(){ orange orange = orangeStore.buyOrange(); orange.setId(UUID.randomUUID().toString().replaceAll("-","")); return orange; } }
public class client { public static void main(String[] args) { //创建已经归纳好方法的外观类 myFacade myFacade = new myFacade(); //购买水果 apple apple = myFacade.buyAppleByfacade(); banana banana = myFacade.buyBananaByfacade(); orange orange = myFacade.buyOrangeByfacade(); System.out.println(apple); System.out.println(banana); System.out.println(orange); } }
这时候我们不需要创建商店了,只需要创建外观类调用买水果方法即可。
外观模式优点:假如水果有1000种,那么我们就要创建1000个对象,而使用外观模式,只需要创建一个外观类的对象即可,只需要1个对象。这样对比起来就相当明显了。。。。。。。。。。。。。。。。。。
桥接模式
使用桥接类和需要被桥接的接口进行桥接
案例:假设我们需要一个接口,用来连接mysql或者Oracle
public interface connection { public void connectDatasource(); }
public class connection_mysql implements connection { /* 连接mysql数据源 */ @Override public void connectDatasource() { System.out.println("mysql数据源连接成功!!!"); } }
public class connection_oracle implements connection { /* 连接Oracle数据源 */ @Override public void connectDatasource() { System.out.println("oracle数据源连接成功!!!"); } }
传统方式测试:
public class client_chuantong { public static void main(String[] args) { //传统方法调用接口方法 connection connection=new connection_mysql(); connection.connectDatasource(); connection connection1=new connection_oracle(); connection.connectDatasource(); } }
桥的抽象类:
public abstract class bridge { /** * 桥的抽象类 */ public abstract void connection(); }
桥的实现类
public class bridgeImpl extends bridge { /** * 核心 * 使用了桥接模式之后,我们只需要创建桥接 */ private connection connection; //给对象注入 public bridgeImpl(connection connection){ this.connection=connection; } //桥接方法(桥接接口方法) @Override public void connection() { connection.connectDatasource(); } }
桥接测试:
public class client_bridge { public static void main(String[] args) { //使用桥接实现类调用被桥接的接口方法 bridge bridge = new bridgeImpl(new connection_oracle()); bridge.connection(); } }
观察者模式
既然有观察者,那么也就有被观察者。一个被观察者被多个观察者观察。比如说天气预报,天气预报就是被观察者,订阅了天气预报的人就是观察者,天气预报需要通知观察者。
被观察者接口:
public interface observerable { /** * 被观察者 */ //添加观察者 public void addObserver(observer observer); //移除观察者 public void removeObserver(observer observer); //通知所有观察者 public void notifyAllObserver(); }
观察者接口:
public interface observer { /** * 观察者 */ //接收通知的方法 public void getTianqi(tianqi tianqi); }
被观察者(在这是天气预报):
public class tianqi implements observerable { /** * 被观察者 :天气预报 */ private String date;//日期 private String wendu;//摄氏度 private List
观察者:
public class person implements observer { /** * 人:观察者 */ private String name; //观察者名字 public person(String name){ this.name=name; } @Override public void getTianqi(tianqi tianqi) { System.out.println("当前用户名为:"+name+","+tianqi); } }
客户端(测试):
public class client { public static void main(String[] args) { tianqi tianqi = new tianqi(); tianqi.addObserver(new person("小明")); tianqi.addObserver(new person("小华")); tianqi.notifyAllObserver(); System.out.println("=======修改后"); tianqi.addObserver(new person("小刘")); tianqi.setDate("2021/5/10"); tianqi.setWendu("15°C"); tianqi.notifyAllObserver(); } }
备忘录模式
备忘录模式:可以用来备份数据和恢复
备忘录需要有三个类:需要备份的类、originator(生成需要备份的类的对象),存储数据和恢复数据的类
责任链模式
策略模式
模板模式
Java 网站
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。