我们都知道,可以使用两种方式给一个类或者对象添加行为。
一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。
二是使用关联。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。
与继承相比,关联关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象。
一、基本定义
装饰者模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。
二、模式结构
装饰者模式UML结构图。
Component: 抽象构件。是定义一个对象接口,可以给这些对象动态地添加职责。
ConcreteComponent:具体构件。是定义了一个具体的对象,也可以给这个对象添加一些职责。
Decorator: 抽象装饰类。是装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来说,是无需知道Decorator存在的。
ConcreteDecorator:具体装饰类,起到给Component添加职责的功能。
三、实现装饰者模式
情景模式:星巴兹以扩张速度快而闻名。在里面购买咖啡时,可以要求在其中加入各种调料,星巴兹会根据所加入的调料收取不同的费用,也就是说不同的咖啡与调料之间有N多不同的组合方式。每种咖啡和调料都有不同的收费。如果这个时候我们使用继承方式,则会陷入无以复加的地步。这里会有N多个类,出现“类爆炸”现象。
结构图如下:
装饰者模式提供了一个比较好的解决方案。
编码实现:
Component Beverage.java
public abstract class Beverage { protected String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
四个组件:HouseBlend.java
public class HouseBlend extends Beverage { public HouseBlend(){ description = "HouseBlend"; } @Override public double cost() { return 0.89; } }
DarkRoast.java
public class DarkRoast extends Beverage { public DarkRoast(){ description = "DarkRoast"; } @Override public double cost() { return 1.05; } }
Espresso.java
public class DarkRoast extends Beverage { public DarkRoast(){ description = "DarkRoast"; } @Override public double cost() { return 1.05; } }
将某个插件的目标绑定到生命周期的某个阶段。
假设把maven-source-plugin插件的jar-no-fork目标绑定到default的verify阶段。(jar-no-fork主要用来创建项目的源码jar包)
在pom.xml的根元素下添加以下内容:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-source-plugin</artifactId> <version>2.1.1</version> <executions> <execution> <id>attach-sources</id> <phase>verify</phase> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
执行mvn命令
mvn clean install
从控制台输出可以看到在插件maven-jar-plugin插件执行jar目标后,紧接着执行verify阶段的jar-no-fork目标:
[INFO] [INFO] --- maven-jar-plugin:2.3.2:jar (default-jar) @ bus-location --- [INFO] Building jar: G:\bus-location\target\bus-location-1.0.jar [INFO] [INFO] --- maven-source-plugin:2.1.1:jar-no-fork (attach-sources) @ bus-location ---
打开maven项目的target目录,可以找到生成的sources jar包
系统:Windows7
使用软件: Maven3.0.3 + Eclipse Indigo JEE
安装Maven
1. 下载解压缩Maven3.0.3,放在某一个目录下
我的目录为:D:\study\greensoft\apache-maven-3.0.3
2. 确认JDK环境已经配置好,JAVA_HOME环境变量配置好。
3. 配置环境变量M2_HOME为Maven的方目录
我的配置为:M2_HOME=D:\study\greensoft\apache-maven-3.0.3
4. 增加Path配置到Maven的bin目录:如...;%M2_HOME%\bin;
打开Dos,输入: mvn -v 结果显示正常表示Maven安装完成
配置Maven
配置Maven包括两点:
一点是Maven的本地仓库目录设置,默认仓库目录是${user}/.m2/repository,这里有很多不便之处,如该目录在C盘,我有时喜欢还原一下系统,忘记备份就不好了; 同时这个仓库只对当前用户有效,其它用户又会在自己的用户目录下建库,那就浪费了,这点对个人PC倒是没什么。总之这个目录最好改在一个安全公用的目录里。
第二点,就是Maven的全局配置文件M2_HOME/conf/settings.xml,需要修改一下,以便更好的支持一些功能。
这两点的修改都只需要修改settings.xml文件就行了:
<!-- localRepository 设置本地库的路径:我直接修改在Maven主目录下的repository目录中 --> <localRepository>${env.M2_HOME}/repository</localRepository> <proxies> <!-- proxy 设置网络连接的代理,现在的公司一般都会通过代理上网 --> <proxy> <id>我的公司</id> <active>true</active> <protocol>http</protocol> <username></username> <password></password> <host>10.1.2.188</host> <port>80</port> <nonProxyHosts>local.*</nonProxyHosts> </proxy> </proxies> <pluginGroups> <!-- pluginGroup 在调试maven的web程序时可能会用的jetty插件,以后就可以直接使用mvn jetty:run 等命令了 --> <pluginGroup>org.mortbay.jetty</pluginGroup> </pluginGroups>
安装Maven的Eclipse插件m2e
1. 登陆Apache Maven的官方网站,找到Eclipse IDE的插件安装地址,如2011-10-13可用地址为:http://download.eclipse.org/technology/m2e/releases
2. 使用Eclipse的在线插件安装安装该插件
打开eclipse,选择new-->Project...可以看到多了一个Maven组,下有Maven Project等,说明插件安装成功。
配置Maven插件m2eclipse
1. 配置Maven的版本。在安装插件后,eclipse默认使用的是插件内嵌的maven,版本和使用的配置文件与我们在Dos中使用的是不一致的,这样就会出现很多问题。比如我们已经换了本地仓库,插件还会使用默认的位置作为本地仓库。
打开 preference-->Maven-->Installations
点击Add...,选择我们自己安装的Maven目