1.概述
结构设计模式是通过识别大型对象结构之间的关系而简化大型对象结构设计的模式。它们描述了构成类和对象的通用方法,以使它们可以作为解决方案重复使用。
四人帮Gang of Four已经描述了七种这样的结构方式或模式。在本快速教程中,我们将看到一些示例,这些示例说明了Java中的某些核心库如何采用它们中的每一个。
2.适配器设计模式
顾名思义,适配器充当中介,将原本不兼容的接口转换为客户端期望的接口。
这在我们要采用一个无法修改其源代码并使其与另一个类一起使用的现有类的情况下很有用。
JDK的收集框架提供了许多适配器模式示例:
List<String> musketeers = Arrays.asList("Athos", "Aramis", "Porthos");
在这里, Arrays#asList
帮助我们将Array
调整为List
。
I / O框架也广泛使用此模式。作为示例,让我们考虑以下代码段,该代码段将InputStream
映射到Reader
对象:
InputStreamReader input = new InputStreamReader(new FileInputStream("input.txt"));
3.桥设计模式
桥接模式允许抽象和实现之间的分离,以便它们可以彼此独立地开发,但仍然具有共存和交互的方式或桥接。
Java中的一个示例是JDBC API。它充当Oracle,MySQL和PostgreSQL等数据库及其特定实现之间的链接。
JDBC API是一组标准接口,例如Driver
, Connection
和ResultSet,
仅举几例。这使不同的数据库供应商可以有各自的实现。
例如,要创建与数据库的连接,我们会说:
Connection connection = DriverManager.getConnection(url);
在这里, url
是一个可以代表任何数据库供应商的字符串。
例如,对于PostgreSQL,我们可能有:
String url = "jdbc:postgresql://localhost/demo";
对于MySQL:
String url = "jdbc:mysql://localhost/demo";
4.组合设计模式
这种模式处理对象的树状结构。在这棵树中,单个对象甚至整个层次结构都以相同的方式处理。用简单的话来说,此模式以分层的方式排列对象,以便客户端可以与整个部分无缝地工作。
AWT / Swing中的嵌套容器是核心Java中复合模式用法的一个很好的例子。 java.awt.Container
对象基本上是一个根组件,可以包含其他组件,从而形成嵌套组件的树形结构。
考虑以下代码片段:
JTabbedPane pane = new JTabbedPane();
pane.addTab("1", new Container());
pane.addTab("2", new JButton());
pane.addTab("3", new JCheckBox());
此处使用的所有类(即JTabbedPane
, JButton
, JCheckBox
和JFrame
)都是Container
后代。如我们所见,此代码段在第二行中以处理子节点的方式处理树或Container
的根。
5.装饰器设计模式
当我们想要增强对象的行为而不修改原始对象本身时,这种模式就会起作用。这是通过将相同类型的包装添加到对像以使其承担附加责任来实现的。
可以在java.io
包中找到此模式最普遍的用法之一:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("test.txt")));
while (bis.available() > 0) {
char c = (char) bis.read();
System.out.println("Char: " + c);
}
在这里, BufferedInputStream
修饰了FileInputStream
以添加缓冲输入的功能。值得注意的是,这两个类都具有InputStream
作为公共祖先。这意味着装饰的对象和装饰的对象是同一类型。这是装饰器模式的明确指示。
6.门面设计模式
根据定义,外墙一词是指物体的虚假外观。应用于编程时,它类似地意味着为复杂的对象集提供另一面(或更确切地说,界面) 。
当我们想要简化或隐藏子系统或框架的复杂性时,这种模式就会发挥作用。
Faces API的ExternalContext
是外观模式的绝佳示例。它在内部使用HttpServletRequest
, HttpServletResponse
和HttpSession
。基本上,它是一个类,它允许Faces API幸福地意识到其底层应用程序环境。
让我们看一下**Primefaces**
是如何使用它来编写HttpResponse
,而实际上并不知道:
protected void writePDFToResponse(ExternalContext externalContext, ByteArrayOutputStream baos, String fileName)
throws IOException, DocumentException {
externalContext.setResponseContentType("application/pdf");
externalContext.setResponseHeader("Expires", "0");
// set more relevant headers
externalContext.setResponseContentLength(baos.size());
externalContext.addResponseCookie(
Constants.DOWNLOAD_COOKIE, "true", Collections.<String, Object>emptyMap());
OutputStream out = externalContext.getResponseOutputStream();
baos.writeTo(out);
// do cleanup
}
正如我们在这里看到的,我们直接使用ExternalContext
作为外观来设置响应头,实际响应和cookie。 HTTPResponse
不在图片中。
7.flyweight设计模式
flyweight模式通过回收对象来减轻我们对象的重量或内存占用。换句话说,如果我们有不可变的对象可以共享状态,那么按照这种模式,我们可以缓存它们以提高系统性能。
Flyweight可以在Java的所有Number
类中发现。
用于创建任何数据类型的包装器类的对象的valueOf
方法旨在缓存值,并在需要时返回它们。
例如, Integer
有一个静态类IntegerCache,
它可以帮助其valueOf
方法始终缓存-128至127范围内的值:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high) {
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}
8.代理设计模式
这种模式提供了另一个复杂对象的代理或替代。虽然听起来与立面相似,但是实际上,立面为客户端提供了与客户端进行交互的不同界面,这实际上是不同的。对于代理,接口与其隐藏的对象的接口相同。
使用此模式,可以在原始对象创建之前或之后对原始对象执行任何操作。
JDK为代理实现提供了一个现成的java.lang.reflect.Proxy
类:
Foo proxyFoo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class }, handler);
上面的代码段为接口Foo
创建了一个代理proxyFoo
。
9.结论
在这个简短的教程中,我们看到了在核心Java中实现的结构设计模式的实际用法。
总而言之,我们简要定义了七个模式分别代表什么,然后通过代码片段逐一理解它们。
0 评论