首页 文章 精选 留言 我的

精选列表

搜索[Java],共10000篇文章
优秀的个人博客,低调大师

Java设计模式之原型模式

​ 一、概述 原型模式(Prototype Pattern)用于创建重复的对象,同时又能保证性能。它属于创建型设计模式,它提供了一种创建对象的最佳方法。 这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的数据库操作之后被创建。我们可以缓存该对象,在下一个请求时返回它的克隆,在需要的时候更新数据库,以此来减少数据库调用。 二、介绍 意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。主要解决:在运行期建立和删除模型。何时使用: 当一个系统应该独立于它的产品创建,构成和表示时。 当要实例化的类是在运行时指定时,例如,通过动态装载。 为了避免一个与产品类层次平行的工厂类层次时。 当一个类的实例只能有几个不同状态组合中的一种时。创建相应数目的原型并克隆它们可能比每次用何时的状态手工实例化该类更方便一些。 如何解决:利用已有的一个原型对象,快速地生成和原型对象一样的实例。 实现克隆操作,继承Cloneable,重写clone()方法。 原型模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有稳定的接口。 应用实例:细胞分裂;Object的clone()方法。优点:性能提高;逃避构造函数的约束。缺点: 配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 必须实现Cloneable接口。 使用场景: 资源优化场景。 类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。 性能和安全要求的场景。 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。 一个对象多个修改者的场景。 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。 在实际项目中,原型模式很少单独出现,一般是和工厂模式一起出现,通过clone方法创建一个对象,然后由工厂方法提供给调用者。 注意事项:与通过对一个类进行实例化来构造新对象不同的是,原型模式是通过拷贝一个现有对象生成新对象的。浅拷贝实现Cloneable,重写,深拷贝是通过实现Serializable读取二进制流。 三、实现 我们将创建一个抽象类 Shape 和扩展了 Shape 类的实体类。下一步是定义类ShapeCache,该类把shape对象存储在一个Hashtable中,并在请求的时候返回他们的克隆。具体UML图如下: 步骤1 创建一个实现了Cloneable接口的抽象类 Shape: public abstract class Shape implements Cloneable { private String id; protected String type; abstract void draw(); public String getType(){ return type; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } } 步骤2 创建扩展了上面抽象类的实体类: //Rectangle public class Rectangle extends Shape { public Rectangle(){ type = "Rectangle"; } @Override public void draw() { System.out.println("Inside Rectangle::draw() method."); } } //Square public class Square extends Shape { public Square(){ type = "Square"; } @Override public void draw() { System.out.println("Inside Square::draw() method."); } } //Circle public class Circle extends Shape { public Circle(){ type = "Circle"; } @Override public void draw() { System.out.println("Inside Circle::draw() method."); } } 步骤3 创建一个类,从数据库获取实体类,并把它们存储在一个Hashtable中。 public class ShapeCache { private static Hashtable<String, Shape> shapeMap = new Hashtable<String, Shape>(); public static Shape getShape(String shapeId) { Shape cachedShape = shapeMap.get(shapeId); return (Shape) cachedShape.clone(); } // 对每种形状都运行数据库查询,并创建该形状 // shapeMap.put(shapeKey, shape); // 例如,我们要添加三种形状 public static void loadCache() { Circle circle = new Circle(); circle.setId("1"); shapeMap.put(circle.getId(),circle); Square square = new Square(); square.setId("2"); shapeMap.put(square.getId(),square); Rectangle rectangle = new Rectangle(); rectangle.setId("3"); shapeMap.put(rectangle.getId(),rectangle); } } 步骤4 测试类: public class PrototypePatternDemo { public static void main(String[] args) { ShapeCache.loadCache(); Shape clonedShape = (Shape) ShapeCache.getShape("1"); System.out.println("Shape : " + clonedShape.getType()); Shape clonedShape2 = (Shape) ShapeCache.getShape("2"); System.out.println("Shape : " + clonedShape2.getType()); Shape clonedShape3 = (Shape) ShapeCache.getShape("3"); System.out.println("Shape : " + clonedShape3.getType()); } } 输出结果: Shape : Circle Shape : Square Shape : Rectangle

优秀的个人博客,低调大师

JAVA设计模式(2)建造者模式

1 定义 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 类型:创建类模式。 四个要素: 产品类:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。在本类图中,产品类是一个具体的类,而非抽象类。实际编程中,产品类可以是由一个抽象类与它的不同实现组成,也可以是由多个抽象类与他们的实现组成。 抽象建造者:引入抽象建造者的目的,是为了将建造的具体过程交与它的子类来实现。这样更容易扩展。一般至少会有两个抽象方法,一个用来建造产品,一个是用来返回产品。 建造者:实现抽象类的所有未实现的方法,具体来说一般是两项任务:组建产品;返回组建好的产品。 导演类:负责调用适当的建造者来组建产品,导演类一般不与产品类发生依赖关系,与导演类直接交互的是建造者类。一般来说,导演类被用来封装程序中易变的部分。 2 代码实现 class Product { private String name; private String type; public void showProduct(){ System.out.println(“名称:”+name); System.out.println(“型号:”+type); } public void setName(String name) { this.name = name; } public void setType(String type) { this.type = type; } } abstract class Builder { public abstract void setPart(String arg1, String arg2); public abstract Product getProduct(); } class ConcreteBuilder extends Builder { private Product product = new Product(); public Product getProduct() { return product; } public void setPart(String arg1, String arg2) { product.setName(arg1); product.setType(arg2); } } public class Director { private Builder builder = new ConcreteBuilder(); public Product getAProduct(){ builder.setPart(“宝马汽车”,“X7”); return builder.getProduct(); } public Product getBProduct(){ builder.setPart(“奥迪汽车”,“Q5”); return builder.getProduct(); } } public class Client { public static void main(String[] args){ Director director = new Director(); Product product1 = director.getAProduct(); product1.showProduct(); Product product2 = director.getBProduct(); product2.showProduct(); } } 3 比较及总结 建造者模式的优点: 首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。 其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。 建造者模式与工厂模式的区别: 建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。 与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。 总结: 建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式

优秀的个人博客,低调大师

Java描述设计模式(16):代理模式

本文源码:GitHub·点这里 || GitEE·点这里 一、生活场景 1、场景描述 在电商高速发展的今天,快递的数量十分庞大,甚至出现了快递代理行业,简单的说就是快递的主人没有时间收快递,会指定一个快递的代收点,比如快递柜,快递驿站等,然后等有时间的时候再过去取,下面使用代码对这个场景进行简单的描述。 2、场景图解 3、源码实现 public class C01_InScene { public static void main(String[] args) { /*自己收快递的测试方式*/ GetExpress getExpress = new GetExpress(); getExpress.sureInfo(); getExpress.signName("张三"); /*代收快递的测试方式*/ ExpressAct getUser = new GetExpress(); ExpressAct getProxy = new ProxyExpress(getUser); getProxy.sureInfo(); getProxy.signName("李四"); } } /** * 接收一个快递的动作接口:确认信息,签名 */ interface ExpressAct{ void sureInfo(); void signName(String name); } /** * 定义一个类接收快递:自己去拿快递 */ class GetExpress implements ExpressAct{ @Override public void sureInfo() { System.out.println("请确认你的个人信息!"); } @Override public void signName(String name) { System.out.println("你的名字是:"+name); } } /** * 定义一个类接收快递:找人代领快递 */ class ProxyExpress implements ExpressAct{ private ExpressAct expressAct=null; public ProxyExpress(ExpressAct expressAct){ this.expressAct = expressAct; } @Override public void sureInfo() { this.expressAct.sureInfo(); } @Override public void signName(String name) { this.expressAct.signName(name); } } 二、代理模式 1、概念描述 代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。所谓代理,就是一个对象代表另一个对象执行相应的动作程序。而代理对象可以在客户端和目标对象之间起到中介的作用。 2、模式图解 3、核心角色 抽象对象角色 声明目标对象和代理对象的共同接口。 目标对象角色 定义了代理对象所代表的目标对象。 代理对象角色 代理对象内部含有目标对象的引用,可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象,AOP编程就是基于这个思想。 4、源码实现 public class C02_Proxy { public static void main(String[] args) { AbstractObject object = new ProxyObject(); object.operation(); } } /** * 抽象对象角色 */ abstract class AbstractObject{ public abstract void operation(); } /** * 目标对象角色 */ class TargetObject extends AbstractObject{ @Override public void operation() { System.out.println("Target Method Run..."); } } /** * 代理对象角色 */ class ProxyObject extends AbstractObject{ TargetObject targetObject = new TargetObject(); @Override public void operation() { System.out.println("Method Before..."); targetObject.operation(); System.out.println("Method After..."); } } 三、JDK动态代理 基于JDK动态代理方式实现AOP切面编程。 1、代码实现 public class C03_JdkProxy { public static void main(String[] args) { BookService bookService = BookAopProxyFactory.createService() ; System.out.println(bookService.getBook()); } } class BookAspect { public void before (){ System.out.println("Method Before ..."); } public void after (){ System.out.println("Method After ..."); } } interface BookService { String getBook () ; } class BookServiceImpl implements BookService { @Override public String getBook() { System.out.println("目标方法【getBook】被执行"); return "高性能MySQL"; } } class BookAopProxyFactory { public static BookService createService() { // 目标类 final BookService bookService = new BookServiceImpl() ; // 切面类 final BookAspect bookAspect = new BookAspect(); /* * 代理类:将目标类(切入点)和 切面类(通知) 结合 */ BookService proxyBookService = (BookService) Proxy.newProxyInstance( BookAopProxyFactory.class.getClassLoader(), bookService.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前执行 bookAspect.before(); // 执行目标类的方法 Object obj = method.invoke(bookService, args); // 后执行 bookAspect.after(); return obj; } }); return proxyBookService ; } } 四、几种常见代理 防火墙代理 内网通过代理穿透防火墙,实现对公网的访问。 缓存代理 为了缓解网站并发压力,在请求数据库资源时,先取缓存中代理的数据,如果缓存未命中,再到数据库取数据,然后缓存取到的数据。 远程代理 远程对象的本地代理对象,通过它可以把远程对象当本地对象调用 。远程代理通过网络和调用的远程对象进行信息交互 。 同步代理 主要使用在多线程编程中,完成多线程间同步工作。 五、源代码地址 GitHub·地址 https://github.com/cicadasmile/model-arithmetic-parent GitEE·地址 https://gitee.com/cicadasmile/model-arithmetic-parent

资源下载

更多资源
Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册