当前位置: 首页 > news >正文

高端品牌网站建设网站开发注意什么如何做网站源码

高端品牌网站建设网站开发注意什么,如何做网站源码,wordpress 企业网站主题,辽宁鞍山刚刚发布个人主页#xff1a;金鳞踏雨 个人简介#xff1a;大家好#xff0c;我是金鳞#xff0c;一个初出茅庐的Java小白 目前状况#xff1a;22届普通本科毕业生#xff0c;几经波折了#xff0c;现在任职于一家国内大型知名日化公司#xff0c;从事Java开发工作 我的博客金鳞踏雨 个人简介大家好我是金鳞一个初出茅庐的Java小白 目前状况22届普通本科毕业生几经波折了现在任职于一家国内大型知名日化公司从事Java开发工作 我的博客这里是CSDN是我学习技术总结知识的地方。希望和各位大佬交流共同进步 ~ 使用组合替代继承对原生对象的方法做增强增加新的行为和能力。 一、实现原理 装饰器设计模式Decorator是一种结构型设计模式它允许动态地为对象添加新的行为。它通过创建一个包装器来实现即将对象放入一个装饰器类中再将装饰器类放入另一个装饰器类中以此类推形成一条包装链。 在不改变原有对象的情况下动态地添加新的行为或修改原有行为。 代码实现 1、定义一个接口或抽象类作为被装饰对象的基类。 public interface Component {void operation(); } 在这个示例中我们定义了一个名为 Component 的接口它包含一个名为 operation 的抽象方法用于定义被装饰对象的基本行为。 2、定义一个具体的被装饰对象实现基类中的方法。 public class ConcreteComponent implements Component {Overridepublic void operation() {System.out.println(ConcreteComponent is doing something...);} } 在这个示例中我们定义了一个名为 ConcreteComponent 的具体实现类实现了 Component 接口中的 operation 方法。 3、定义一个抽象装饰器类继承基类并将被装饰对象作为属性。 public abstract class Decorator implements Component {// 装饰器设计模式 使用组合的形式进行装饰protected Component component;public Decorator(Component component) {this.component component;}Overridepublic void operation() {component.operation();} } 在这个示例中我们定义了一个名为 Decorator 的抽象类继承了 Component 接口并将被装饰对象作为属性。在 operation 方法中我们调用被装饰对象的同名方法。 4、定义具体的装饰器类继承抽象装饰器类并实现增强逻辑。 public class ConcreteDecoratorA extends Decorator {public ConcreteDecoratorA(Component component) {System.out.println(这是第一次包装...);super(component);}Overridepublic void operation() {super.operation();System.out.println(ConcreteDecoratorA is adding new behavior...);} }public class ConcreteDecoratorB extends Decorator {public ConcreteDecoratorB(Component component) {System.out.println(这是第二次包装...);super(component);}Overridepublic void operation() {super.operation();System.out.println(ConcreteDecoratorB is adding new behavior...);} } 在这个示例中我们定义了一个名为 ConcreteDecoratorA 的具体装饰器类继承了 Decorator 抽象类并实现了 operation 方法的增强逻辑。在 operation 方法中我们先调用被装饰对象的同名方法然后添加新的行为。 5、使用装饰器增强被装饰对象。 public class Main {public static void main(String[] args) {Component component new ConcreteComponent();// 进行第一次包装component new ConcreteDecoratorA(component);// 进行第二次包装component new ConcreteDecoratorB(component);component.operation();} } 在这个示例中我们先创建了一个被装饰对象 ConcreteComponent然后通过 ConcreteDecoratorA 类创建了一个装饰器并将被装饰对象作为参数传入。最后调用装饰器的 operation 方法这样就可以实现对被装饰对象的增强。 装饰器设计模式包装后可以继续包装...类似于套娃。一层一层逐步增强 装饰器与静态代理的区别 装饰器模式和静态代理模式最大的区别——目的不同 代理模式的目的是为了控制对对象的访问它在对象的外部提供一个代理对象来控制对原始对象的访问。代理对象和原始对象通常实现同一个接口或继承同一个类以保证二者可以互相替代。 装饰器模式的目的是为了动态地增强对象的功能它在对象的内部通过一种包装器的方式来实现。装饰器模式中装饰器类和被装饰对象通常实现同一个接口或继承同一个类以保证二者可以互相替代。装饰器模式也被称为包装器模式。 需要注意的是装饰器模式虽然可以实现动态地为对象增加行为但是会增加系统的复杂性因此在使用时需要仔细权衡利弊。 二、使用场景 在 Java 中装饰器模式的应用非常广泛特别是在 I/O 操作中。Java 中的 I/O 类库就是使用装饰器模式来实现不同的数据流之间的转换和增强的。 1.从IO库的设计理解装饰器 打开文件 test.txt从中读取数据。 其中InputStream 是一个抽象类FileInputStream 是专门用来读取文件流的子类。BufferedInputStream 是一个支持带缓存功能的数据读取类可以提高数据读取的效率 InputStream in new FileInputStream(D:/test.txt); InputStream bin new BufferedInputStream(in); byte[] data new byte[128]; while (bin.read(data) ! -1) {//... } 初看上面的代码我们会觉得 Java IO 的用法比较麻烦需要先创建一个 FileInputStream 对象然后再传递给 BufferedInputStream 对象来使用。 为什么Java IO 为什么不设计一个继承 FileInputStream 并且支持缓存的 BufferedFileInputStream 类呢 这样直接创建一个 BufferedFileInputStream 类对象打开文件读取数据用起来岂不是更加简单 InputStream bin new BufferedFileInputStream(/user/wangzheng/test.txt); byte[] data new byte[128]; while (bin.read(data) ! -1) {//... } 1基于继承的设计方案能实现不靠谱 如果 InputStream 只有一个子类 FileInputStream 的话那我们在 FileInputStream 基础之上再设计一个孙子类 BufferedFileInputStream这样子是完全可以的毕竟继承结构还算简单 但实际上继承 InputStream 的子类有很多。我们需要给每一个 InputStream 的子类再继续派生支持缓存读取的子类。 除了支持缓存读取之外如果我们还需要对功能进行其他方面的增强比如下面的 DataInputStream 类支持按照基本数据类型int、boolean、long 等来读取数据。 FileInputStream in new FileInputStream(/user/wangzheng/test.txt); DataInputStream din new DataInputStream(in); int data din.readInt(); 在这种情况下如果我们继续按照继承的方式来实现的话就需要再继续派生出 DataFileInputStream、DataPipedInputStream 等类。如果我们还需要既支持缓存、又支持按照基本类型读取数据的类那就要再继续派生出 BufferedDataFileInputStream、BufferedDataPipedInputStream 等 n 多类。 这还只是附加了两个增强功能如果我们需要附加更多的增强功能那就会导致组合爆炸类继承结构变得无比复杂代码既不好扩展也不好维护。 2基于装饰器模式的设计方案 组合优于继承建议使用组合来替代继承 针对刚刚的继承结构过于复杂的问题我们可以通过将继承关系改为组合关系来解决。 public abstract class InputStream {//...public int read(byte b[]) throws IOException {return read(b, 0, b.length);}public int read(byte b[], int off, int len) throws IOException {//...}public long skip(long n) throws IOException {//...}public int available() throws IOException {return 0;}public void close() throws IOException {}public synchronized void mark(int readlimit) {}public synchronized void reset() throws IOException {throw new IOException(mark/reset not supported);}public boolean markSupported() {return false;} }public class BufferedInputStream extends InputStream {protected volatile InputStream in;protected BufferedInputStream(InputStream in) {this.in in;}//...实现基于缓存的读数据接口... }public class DataInputStream extends InputStream {protected volatile InputStream in;protected DataInputStream(InputStream in) {this.in in;}//...实现读取基本类型数据的接口 } 那装饰器模式就是简单的“用组合替代继承”吗 当然不是从 Java IO 的设计来看装饰器模式相对于简单的组合关系还有两个比较特殊的地方 1、装饰器类和原始类继承同样的父类这样我们可以对原始类“嵌套”多个装饰器类。 比如下面这样一段代码我们对 FileInputStream 嵌套了两个装饰器类BufferedInputStream 和 DataInputStream让它既支持缓存读取又支持按照基本数据类型来读取数据。 // 逐次增强 InputStream in new FileInputStream(/user/wangzheng/test.txt); InputStream bin new BufferedInputStream(in); DataInputStream din new DataInputStream(bin); int data din.readInt(); 2、装饰器类是对功能的增强这也是装饰器模式应用场景的一个重要特点。 实际上符合“组合关系”这种代码结构的设计模式有很多比如之前讲过的代理模式还有现在的装饰器模式。尽管它们的代码结构很相似但是每种设计模式的意图是不同的 例如代理模式中代理类附加的是跟原始类无关的功能而在装饰器模式中装饰器类附加的是跟原始类相关的增强功能。 // 代理模式的代码结构(下面的接口也可以替换成抽象类) public interface IA {void f(); } public class A impelements IA {public void f() { //... } } public class AProxy impements IA {private IA a;public AProxy(IA a) {this.a a;}public void f() {// 新添加的代理逻辑a.f();// 新添加的代理逻辑} }// 装饰器模式的代码结构(下面的接口也可以替换成抽象类) public interface IA {void f(); } public class A impelements IA {public void f() {// ...} } public class ADecorator impements IA {private IA a;public ADecorator(IA a) {this.a a;}public void f() {// 功能增强代码a.f();// 功能增强代码} } BufferedInputStream为什么不直接继承InputStream 实际上如果去查看 JDK 的源码你会发现BufferedInputStream、DataInputStream 并非继承自 InputStream而是另外一个叫 FilterInputStream 的类。那这又是出于什么样的设计意图才引入这样一个类呢 InputStream 是一个抽象类而非接口而且它的大部分函数比如 read()、available()都有默认实现按理来说我们只需要在 BufferedInputStream 类中重新实现那些需要增加缓存功能的函数就可以了其他函数继承 InputStream 的默认实现。但实际上这样做是行不通的 对于即便是不需要增加缓存功能的函数来说BufferedInputStream 还是必须把它重新实现一遍简单包裹对 InputStream 对象的函数调用如果不重新实现那 BufferedInputStream 类就无法将最终读取数据的任务委托给传递进来的 InputStream 对象来完成。 public class BufferedInputStream extends InputStream {protected volatile InputStream in;protected BufferedInputStream(InputStream in) {this.in in;}// f()函数不需要增强只是重新调用一下InputStream in对象的f()public void f() {in.f();} } 实际上DataInputStream 也存在跟 BufferedInputStream 同样的问题。为了避免代码重复Java IO 抽象出了一个装饰器父类 FilterInputStream。 InputStream 的所有的装饰器类BufferedInputStream、DataInputStream都继承自这个装饰器父类。这样装饰器类只需要实现它需要增强的方法就可以了其他方法继承装饰器父类的默认实现。 public class FilterInputStream extends InputStream {protected volatile InputStream in;protected FilterInputStream(InputStream in) {this.in in;}public int read() throws IOException {return in.read();}public int read(byte b[]) throws IOException {return read(b, 0, b.length);}public int read(byte b[], int off, int len) throws IOException {return in.read(b, off, len);}public long skip(long n) throws IOException {return in.skip(n);}public int available() throws IOException {return in.available();}public void close() throws IOException {in.close();}public synchronized void mark(int readlimit) {in.mark(readlimit);}public synchronized void reset() throws IOException {in.reset();}public boolean markSupported() {return in.markSupported();} } 总的来说当 BufferedInputStream 继承自 FilterInputStream 时它可以非常轻松地扩展 FilterInputStream 的行为从而实现了输入流的缓冲功能。如果 BufferedInputStream 直接继承自 InputStream那么它就需要重新实现所有 InputStream 的方法包括一些可能不需要修改的方法这会使代码变得复杂且容易出错。 2.MyBatis的缓存设计 创建缓存的过程 useNewCache方法用于配置Mapper是否使用一个全新的缓存实例而不共享缓存实例 public Cache useNewCache(Class? extends Cache typeClass,Class? extends Cache evictionClass,Long flushInterval,Integer size,boolean readWrite,boolean blocking,Properties props) {Cache cache new CacheBuilder(currentNamespace)// 根据类型生成实例并进行配置.implementation(valueOrDefault(typeClass, PerpetualCache.class)).addDecorator(valueOrDefault(evictionClass, LruCache.class)) // 添加装饰器.clearInterval(flushInterval).size(size).readWrite(readWrite).blocking(blocking).properties(props).build();configuration.addCache(cache);currentCache cache;return cache; } 默认的缓存如下本质就是维护了一个简单的HashMap public class PerpetualCache implements Cache {private final String id;private final MapObject, Object cache new HashMap();public PerpetualCache(String id) {this.id id;}Overridepublic void putObject(Object key, Object value) {cache.put(key, value);}Overridepublic Object getObject(Object key) {return cache.get(key);}// ...省略其他的简单的方法} 缓存的构建过程 public Cache build() {// 设置默认的cache实现并绑定默认的淘汰策略setDefaultImplementations();// 利用反射创建实例Cache cache newBaseCacheInstance(implementation, id);// 设置properties属性setCacheProperties(cache);// 不应用装饰自定义缓存自定义缓存需要自己实现对应的特性如淘汰策略等// 通常情况自定义缓存有自己的独立配置如redis、ehcacheif (PerpetualCache.class.equals(cache.getClass())) {for (Class? extends Cache decorator : decorators) {cache newCacheDecoratorInstance(decorator, cache);setCacheProperties(cache);}// 这是标准的装饰器这里使用了装饰器设计模式cache setStandardDecorators(cache);} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {cache new LoggingCache(cache);}return cache; } MyBatis会使用装饰者设计模式对默认cache进行装饰使其具有LRU的能力 private void setDefaultImplementations() {if (implementation null) {implementation PerpetualCache.class;if (decorators.isEmpty()) {// decorators是成员变量装饰器饰器具备LRU的能力decorators.add(LruCache.class);}} } LruCache实现如下默认情况下的LRU算法实现是基于LinkedHashMap实现的 public class LruCache implements Cache {// 代理目标缓存private final Cache delegate;private MapObject, Object keyMap;private Object eldestKey;// LruCache用来装饰默认的缓存这里实现了缓存的高级特性public LruCache(Cache delegate) {this.delegate delegate;setSize(1024);}Overridepublic String getId() {return delegate.getId();}Overridepublic int getSize() {return delegate.getSize();}// 设置长度构建一个LinkedHashMap重写removeEldestEntrypublic void setSize(final int size) {// 第三个参数accessOrder为true可以使LinkedHashMap维护一个【访问顺序】// 最近被访问的数据会被放在链表的尾部天然实现lrukeyMap new LinkedHashMapObject, Object(size, .75F, true) {private static final long serialVersionUID 4267176411845948333L;// 重写该方法父类直接返回false// 只要实际容量size() 大于 初始化容量 size 认定当前的缓存已经满了// 该方法会在LinkedHashMap的afterNodeInsertion方法中被主动调用// 会将头节点当作eldest删除Overrideprotected boolean removeEldestEntry(Map.EntryObject, Object eldest) {boolean tooBig size() size;if (tooBig) {// 同时将这个这个key复制给成员变量eldestKeyeldestKey eldest.getKey();}return tooBig;}};}// put一个缓存的过程// 放入当前的缓存值淘汰eldestKeyOverridepublic void putObject(Object key, Object value) {delegate.putObject(key, value);cycleKeyList(key);}// get一个缓存的过程// 获得该值同时提升key热度主动访问一下keyMap.get(key)Overridepublic Object getObject(Object key) {keyMap.get(key); return delegate.getObject(key);}Overridepublic Object removeObject(Object key) {return delegate.removeObject(key);}Overridepublic void clear() {delegate.clear();keyMap.clear();}// 循环key的集合private void cycleKeyList(Object key) {keyMap.put(key, key);if (eldestKey ! null) {delegate.removeObject(eldestKey);eldestKey null;}}} 最后使用其他的装饰器对cache进行装饰使其就有更多的能力 private Cache setStandardDecorators(Cache cache) {try {MetaObject metaCache SystemMetaObject.forObject(cache);// 设置大小默认1024if (size ! null metaCache.hasSetter(size)) {metaCache.setValue(size, size);}if (clearInterval ! null) {cache new ScheduledCache(cache);((ScheduledCache) cache).setClearInterval(clearInterval);}if (readWrite) {cache new SerializedCache(cache);}cache new LoggingCache(cache);cache new SynchronizedCache(cache);if (blocking) {cache new BlockingCache(cache);}return cache;} catch (Exception e) {throw new CacheException(Error building standard cache decorators. Cause: e, e);} } 三、总结 装饰器模式主要解决继承关系过于复杂的问题通常是通过组合来替代继承。 它主要的作用是给原始类添加功能。这也是判断是否该用装饰器模式的一个重要的依据。除此之外装饰器模式还有一个特点那就是可以对原始类嵌套使用多个装饰器。为了满足这个应用场景在设计的时候装饰器类需要跟原始类继承相同的抽象类或者接口。 Q: 在学习代理设计模式的时候我们通过装饰者模式给 InputStream 添加缓存读取数据功能。那对于“添加缓存”这个应用场景来说我们到底是该用代理模式还是装饰器模式呢你怎么看待这个问题 事实上对于绝大多数的添加缓存的业务场景核心目的主要就是想增强对象的功能即增加缓存功能而并不是控制对对象的访问所以装饰器模式可能会更合适。但是假如我们想强制对持久层增加一个本地缓存代理设计模式也是很好的选择。 文章到这里就结束了如果有什么疑问的地方可以在评论区指出~ 希望能和大佬们一起努力诸君顶峰相见 再次感谢各位小伙伴儿们的支持
http://www.dnsts.com.cn/news/19232.html

相关文章:

  • 梵克雅宝什么档次临沂网站优化
  • 印度人通过什么网站做国际贸易图片识别
  • 个人网站空间大小烟台网站快速优化排名
  • 易名域名交易郑州seo怎么做
  • 怎么把文件放到网站的根目录网站做代理服务器
  • 如何建设营销型的网站用什么做响应式网站
  • 哪个做问卷网站佣金高做网站需要提供些什么页面
  • app网站样式建网站用什么系统好
  • 外贸网站的特色做网站应规避的风险
  • 公司建站后还要录入网页吗宝塔搭建wordpress网站
  • 使用angular2框架做的网站wordpress页面响应慢
  • 四川省住房与城乡建设厅网站关键词seo排名怎么做的
  • 网页设计与网站规划建网站的公司大全
  • 重庆网站推广公司哪家好网站动图怎么做
  • 设置网站默认首页c语言入门自学零基础
  • 泰安建站哪家好网络推广 推广
  • 怎么做像知乎一样的网站做自己网站
  • 建设市政务信息共享网站wordpress需要先安装数据库
  • wordpress国内打开速度慢福州seo结算
  • 此网站域名三天更换做外贸的人经常用什么网站
  • 做网站买什么服务器 便宜网站制作文章
  • 网站建设会计帐务处理做地推的网站
  • 网站开发培训什么ps设计师网站有哪些
  • 如何自己做网站模版3d建模培训班有用吗
  • 模板网站建设 报价余杭门户网站
  • 现在网站前台用什么做dedecms网站地图
  • 做淘客的网站名称wordpress手机编辑器插件下载地址
  • 李连杰做的功夫网站南宁网站建设 超博网络
  • 关键词没有排名的网站怎么做app制作教程下载
  • 北京监理建设协会网站荆门网站建设