javaEE design patter(2)
以下内容摘自csdn论坛:
工厂模式(Factory)
工厂模式:主要分为三种模式:
定义:在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。
为什么要使用工厂模式:
- 解耦 :把对象的创建和使用的过程分开
- 降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
- 降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
1 简单工厂模式:
在实际的开发当中较少使用,主要在于违背了我们的开放-封闭原则,主要适用于创建对象较少,客户端不关心对象的创建过程方面。
主要的角色分配如下:
- 工厂(Factory)角色 :简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
- 抽象产品(Product)角色 :简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
- 具体产品(Concrete Product)角色:简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例。在这里不做赘述。
2 工厂方法模式:
定义: 工厂方法模式,又称工厂模式、多态工厂模式和虚拟构造器模式,通过定义工厂父类负责定义创建对象的公共接口,而子类则负责生成具体的对象。
- 主要使用的工厂模式步骤如下:
- 创建抽象工厂类,定义具体工厂的公共接口
- 创建抽象产品类定义,具体产品的公共接口
- 创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
- 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
- 最后,外界通过调用具体的工厂类的不同方法,从而创建不同的具体产品类的实例。
工厂方法模式的优点:符合开闭原则,符合单一职责原则。可以形成基于继承的等级结构。
3 抽象工厂模式:
定义:抽象工厂模式,即Abstract Factory Pattern,提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类;具体的工厂负责实现具体的产品实例。(抽象工厂模式与工厂方法模式最大的区别:抽象工厂中每个工厂可以创建多种类的产品;而工厂方法每个工厂只能创建一类。)
- 创建抽象工厂类,定义具体工厂的公共接口
- 创建抽象产品族类 ,定义抽象产品的公共接口
- 创建抽象产品类 (继承抽象产品族类),定义具体产品的公共接口
- 创建具体产品类(继承抽象产品类) & 定义生产的具体产品
- 创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法
- 客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
代理模式
定义:给目标对象提供一个代理对象,并由代理对象控制对目标对象的引用。通过引入代理对象的方式来间接访问目标对象
模式原理图:
- 创建抽象对象接口(Subject):声明你真实对象需要让代理对象做的方法
- 创建真实对象类
- 创建代理对象类(Proxy),并通过代理类创建真实对象实例并访问其方法
- 客户端调用
实现优点:
- 协调调用者和被调用者,降低了系统的耦合度
- 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用
模板方法模式(Template Method)
就是指:一个抽象类中,有一个主方法,再定义1...n个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用
就是在AbstractCalculator类中定义一个主方法calculate,calculate()调用spilt()等,Plus和Minus分别继承AbstractCalculator类,通过对AbstractCalculator的调用实现对子类的调用.
spring AOP capabilities and goals
以下为官方文档原文:
5.2. Spring AOP Capabilities and Goals
Spring AOP is implemented in pure Java. There is no need for a special compilation process. Spring AOP does not need to control the class loader hierarchy and is thus suitable for use in a servlet container or application server.//SpringAOP不需要控制类加载器层次结构,因此适合在servlet容器或应用程序服务器中使用。
Spring AOP currently supports only method execution join points (advising the execution of methods on Spring beans). Field interception is not implemented, although support for field interception could be added without breaking the core Spring AOP APIs. If you need to advise field access and update join points, consider a language such as AspectJ.//SpringAOP目前只支持方法执行连接点(建议在SpringBean上执行方法)。虽然可以在不破坏核心SpringAOAPIs的情况下添加对字段拦截的支持,但没有实现字段拦截。如果需要建议字段访问和更新连接点,请考虑使用AspectJ之类的语言。
Spring AOP’s approach to AOP differs from that of most other AOP frameworks. The aim is not to provide the most complete AOP implementation (although Spring AOP is quite capable). Rather, the aim is to provide a close integration between AOP implementation and Spring IoC, to help solve common problems in enterprise applications.//SpringAOP的AOP方法不同于大多数其他AOP框架。目的并不是提供最完整的AOP实现(尽管SpringAOP非常有能力)。相反,目的是在AOP实现和SpringIOC之间提供紧密的集成,以帮助解决企业应用程序中的常见问题。
Thus, for example, the Spring Framework’s AOP functionality is normally used in conjunction with the Spring IoC container. Aspects are configured by using normal bean definition syntax (although this allows powerful “auto-proxying” capabilities). This is a crucial difference from other AOP implementations. You cannot do some things easily or efficiently with Spring AOP, such as advise very fine-grained objects (typically, domain objects). AspectJ is the best choice in such cases. However, our experience is that Spring AOP provides an excellent solution to most problems in enterprise Java applications that are amenable to AOP.//例如,Spring框架的AOP功能通常与SpringIOC容器一起使用。方面是通过使用普通bean定义语法配置的(尽管这允许强大的“自动代理”功能)。这是与其他AOP实现的关键区别。对于SpringAOP,您不能轻松或高效地执行某些操作,例如建议非常细粒度的对象(通常是域对象)。在这种情况下,AspectJ是最佳选择。然而,我们的经验是,Spring AOP为企业Java应用程序中大多数面向AOP的问题提供了极好的解决方案。
Spring AOP never strives to compete with AspectJ to provide a comprehensive AOP solution. We believe that both proxy-based frameworks such as Spring AOP and full-blown frameworks such as AspectJ are valuable and that they are complementary, rather than in competition. Spring seamlessly integrates Spring AOP and IoC with AspectJ, to enable all uses of AOP within a consistent Spring-based application architecture. This integration does not affect the Spring AOP API or the AOP Alliance API. Spring AOP remains backward-compatible. See the following chapter for a discussion of the Spring AOP APIs.//Spring框架的核心原则之一是无侵略性。这是一种观点,即不应强制您将特定于框架的类和接口引入到您的业务或域模型中。但是,在某些地方,Spring框架确实为您提供了将特定于Spring框架的依赖性引入到代码库中的选项。为您提供这些选项的基本原理是,在某些场景中,以这种方式读取或编码某些特定功能可能非常简单。然而,Spring框架(几乎)总是为您提供了选择:您可以自由地做出一个明智的决定,决定哪个选项最适合您的特定用例或场景。
One of the central tenets of the Spring Framework is that of non-invasiveness. This is the idea that you should not be forced to introduce framework-specific classes and interfaces into your business or domain model. However, in some places, the Spring Framework does give you the option to introduce Spring Framework-specific dependencies into your codebase. The rationale in giving you such options is because, in certain scenarios, it might be just plain easier to read or code some specific piece of functionality in such a way. However, the Spring Framework (almost) always offers you the choice: You have the freedom to make an informed decision as to which option best suits your particular use case or scenario. One such choice that is relevant to this chapter is that of which AOP framework (and which AOP style) to choose. You have the choice of AspectJ, Spring AOP, or both. You also have the choice of either the @AspectJ annotation-style approach or the Spring XML configuration-style approach. The fact that this chapter chooses to introduce the @AspectJ-style approach first should not be taken as an indication that the Spring team favors the @AspectJ annotation-style approach over the Spring XML configuration-style. See Choosing which AOP Declaration Style to Use for a more complete discussion of the “whys and wherefores” of each style. |
5.3. AOP Proxies
Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.
Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces. By default, CGLIB is used if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes, business classes normally implement one or more business interfaces. It is possible to force the use of CGLIB, in those (hopefully rare) cases where you need to advise a method that is not declared on an interface or where you need to pass a proxied object to a method as a concrete type.
It is important to grasp the fact that Spring AOP is proxy-based. See Understanding AOP Proxies for a thorough examination of exactly what this implementation detail actually means.
CDI service
以下内容摘自github:
上下文和依赖注入(CDI)使您的对象能够自动为它们提供依赖项,而不是创建它们或将它们作为参数接收。CDI还为您管理这些依赖项的生命周期。
例如,考虑以下servlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@WebServlet
(
"/cdiservlet"
)
public
class
NewServlet
extends
HttpServlet {
private
Message message;
@Override
public
void
init() {
message =
new
MessageB();
}
@Override
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
IOException {
response.getWriter().write(message.get());
}
}
|
这个servlet需要一个实现Message
接口的对象实例 :
1
2
3
|
public
interface
Message {
public
String get();
}
|
servlet创建自己的以下对象的实例:
1
2
3
4
5
6
7
8
|
public
class
MessageB
implements
Message {
public
MessageB() { }
@Override
public
String get() {
return
"message B"
;
}
}
|
使用CDI,这个servlet可以声明它对Message
实例的依赖性,并让它由CDI运行时自动注入。新的servlet代码如下:(详细分析此段代码)
1
2
3
4
5
6
7
8
9
|
@WebServlet
(
"/cdiservlet"
)
//url映射,即@WebServlet告诉容器,如果请求的URL是"/cdiservlet",则由NewServlet的实例提供服务。
public
class
NewServlet
extends
HttpServlet {
//声明一个NewServlet类 并继承HttpServlet
@Inject
private
Message message;
//表示运行时将动态注入(实例化)一个Message
@Override
//重写父类doGet()方法
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
IOException {
response.getWriter().write(message.get());
//带文本格式打印输出message.get()返回的文本
}
}
|
CDI运行时查找实现Message
接口的MessageB
类,查找类,创建它的新实例,并在运行时将其注入servlet。要管理新实例的生命周期,CDI运行时需要知道实例的范围应该是什么。在此示例中,servlet仅需要实例来处理HTTP请求; 然后可以对实例进行垃圾回收。这是使用javax.enterprise.context.RequestScoped
注释指定的:
1
2
|
@RequestScoped
public
class
MessageB
implements
Message { ... }
|
该MessageB
类是一个CDI bean。CDI bean是CDI可以自动实例化,管理和注入以满足其他对象的依赖关系的类。几乎所有Java类都可以由CDI管理和注入