??xml version="1.0" encoding="utf-8" standalone="yes"?>
工厂Ҏ模式
(Factory Method)
是创建模式的一U,也叫虚拟构造子
(Virture Constractor)
模式或多态性工?/span>
(Polymorphic Factory)
模式?/span>
工厂Ҏ模式定义一个抽象的对象创徏cL接口Q将实际的对象创建工作交l子cL实现?/span>
public interface AbstractProduct{
public void printName();
}
public class ConcreteProduct1 implements AbstractProduct{
public void printName(){
System.out.println(“ConcreteProduct
}
}
public class ConcreteProduct2 implements AbstractProduct{
public void printName(){
System.out.println(“ConcreteProduct
}
}
public interface AbstractFactory {
public AbstractProduct factoryMethod();
}
public class ConcreteFactory1 implements AbstractFactory{
public AbstractProduct factoryMethod(){
//do something.
return new ConcreteProduct1();
}
}
public class ConcreteFactory2 implements AbstractFactory{
public AbstractProduct factoryMethod(){
//do something.
return new ConcreteProduct2();
}
}
工厂Ҏ模式解决了简单工厂模式的一些缺P是在单工厂模式的基础上发展的?/span>
单工厂模式把所有的重心攑ֈ工厂cMQ一旦向pȝ增加新的产品Q就必须修改工厂c,不满_闭原则;工厂Ҏ模式提供一个抽象的工厂接口Q在不同的品结构上实现不同的品工厂具体类来创层次中的产品Q通常一个具体工厂创Z个具体品。在新增产品的时候,只需要实现新的对应工厂就可以满需要,是符合开闭原则的?/span>
工厂Ҏ模式与模板模?/span>
?/span>
java
设计模式?/span>
阎宏
电子工业出版C?/span>
1.
模式定义
2.
模式介绍
2.1.
单类?/span>
2.2.
cd对应CZ代码
2.2.1.
抽象产品Q?/span>
AbstractProduct
2.2.2.
具体产品Q?/span>
ConcreteProduct1
?/span>
ConcreteProduct2
2.2.3.
抽象工厂Q?/span>
AbstractFactory
2.2.4.
具体工厂Q?/span>
ConcreteFactory1
?/span>
ConcreteFactory2
3.
模式特点
3.1.
开闭原则(优点Q?/span>
3.2.
~点
4.
与其它模式的关系
5.
参?/span>
]]>
什么时候用?
1、创ZcL公共接口或父cȝ对象Qƈ要求隐藏具体实现?br />2、隐藏子cȝ创徏Q提高扩展性?br />
优点Q隐藏具体品的创徏Q客L独立的创Z品而不用关心具体的创徏q程Qƈ在引入新的品类时不用修改客戯用类?br />~点Q所用品的创徏集中到factory上,成ؓpȝ的中心,一旦factory出现问题整个pȝ崩溃?br />
标准单工厂模?/strong>
工厂c?/p>
package
pattern.simplefactory;
/** */
/**
* 单工厂模式-工厂c?br />
@author
ZhangPu
*/
public
class
ProductFactory
{
/** */
/**
* 单工厂方法:通过cd路径创徏产品
*
@param
className
*
@return
*/
public
static
Product factory(String className)
{
Product product
=
null
;
try
{
product
=
(Product)Class.forName(className).newInstance();
}
catch
(Exception e)
{
throw
new
RuntimeException(e);
}
return
product;
}
}
抽象产品接口package pattern.simplefactory;
/** *//**
* 产品接口
*/
public interface Product
{
public String getName();
}
具体产品c?br />package pattern.simplefactory;
/** *//**
* 普通?br />
@author ZhangPu
*/
public class ConcreteProduct implements Product
{
private String name = "普通?/span>";
public String getName()
{
return name;
}
}
客户端类package pattern.simplefactory;
/** *//**
* client class
@author ZhangPu
*/
public class Client
{
public static void main(String[] args)
{
Product product = ProductFactory.factory("pattern.simplefactory.ConcreteProduct");
System.out.println(product.getName());
}
}
合ƈ抽象产品和品的单工厂模?br />
合ƈ产品和工厂的模式
h意与单例模式的区别:
1.单例模式构造函数是U有的,不允许外界创建?br />2.单例模式只有一个实例?/font>
]]>
应用实例Q序列键值生成器
本例采用hqldb作ؓ演示数据库。表l构如下Q?br />
CREATE TABLE KEYTABLE(
KEYNAME VARCHAR(32) NOT NULL PRIMARY KEY,
KEYVALUE int NOT NULL
)package pattern.multiton;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
/**//*
* Key service<br>
* table strunction:<br/>
* CREATE TABLE KEYTABLE(<br/>
* KEYNAME VARCHAR(32) NOT NULL PRIMARY KEY,<br/>
* KEYVALUE int NOT NULL<br/>
* )<br>
@author ZhangPu
Feb 22, 2007 4:30:47 PM
*/
public class KeyService
{
private int cache;
private String keyName;
private int maxValue;
private int nextValue;
public KeyService(int cache,String keyName)
{
this.cache = cache;
this.keyName = keyName;
retrieveKey();
}
/** *//**
* get next key form keyinfo
*
* @return
*/
public int getNextKey()
{
if(nextValue >= maxValue)
{
retrieveKey();
}
return nextValue++;
}
/** *//**
* retrieve current value form db.
* @return
*/
private void retrieveKey()
{
System.out.println("retrieve database!");
String sqlUpdate = "update KEYTABLE set KEYVALUE = KEYVALUE + " + cache + " where KEYNAME = '"+keyName+"'";
String sqlSelete = "select KEYVALUE from KEYTABLE where KEYNAME = '"+keyName+"'";
Connection conn = null;
Statement stmt = null;
int keyFormDb = 0;
try
{
Driver driver = (Driver)Class.forName("org.hsqldb.jdbcDriver").newInstance();
DriverManager.registerDriver(driver);
String url = "jdbc:hsqldb:hsql://localhost/pattern";
String user = "sa";
String passwd = "";
conn = DriverManager.getConnection(url,user,passwd);
stmt = conn.createStatement();
stmt.executeUpdate(sqlUpdate);
ResultSet rs = stmt.executeQuery(sqlSelete);
if(rs != null && rs.next())
{
keyFormDb = rs.getInt(1);
}
}catch(Exception e)
{
try
{
stmt.close();
conn.close();
} catch (Exception ex)
{
ex.printStackTrace();
}
e.printStackTrace();
}
maxValue = keyFormDb;
nextValue = keyFormDb - cache;
}
}
import java.util.HashMap;
import java.util.Map;
/*
* KeyGenerator with multiton pattern
@author ZhangPu
Feb 22, 2007 5:55:24 PM
*/
public class KeyGenerator {
/**
* save keyServices
*/
private static Map<String,KeyGenerator> KeyGenerators = new HashMap<String,KeyGenerator>();
/**
* the current instance.
*/
private KeyService keyService;
/**
* cache pool size
*/
private static final int KEY_CACHE = 20;
private KeyGenerator(){}
private KeyGenerator(String keyName){
keyService = new KeyService(KEY_CACHE,keyName);
}
/**
* Multiton instance
* @param keyName
* @return
*/
public synchronized static KeyGenerator getInstance(String keyName){
KeyGenerator keyGenerator;
if(KeyGenerators.containsKey(keyName)){
keyGenerator = KeyGenerators.get(keyName);
}else{
keyGenerator = new KeyGenerator(keyName);
KeyGenerators.put(keyName, keyGenerator);
}
return keyGenerator;
}
/**
* business method.
* @return
*/
public int getNextKey(){
return keyService.getNextKey();
}
}package pattern.multiton;
/**//*
@author ZhangPu
Feb 22, 2007 6:27:22 PM
*/
public class Client
{
public static void main(String[] args)
{
String keyName = "SYS_RESOURCE";
KeyGenerator keyGenerator = KeyGenerator.getInstance(keyName);
for(int i=0;i<20;i++)
{
System.out.println("time"+(i+1)+":"+keyGenerator.getNextKey());
}
}
}
]]>
]]>
本文是自己关于关键字 final 的一些ȝ?/span> final 关键字主要应用在标志和声明类Q成员变量和ҎZ可变Q通过q个基本定义可以扩展?/span> final 可以限制cdҎ的承关pR?/span>
final 变量
final 变量分ؓ单变量和对象变量。声?/span> final 的简单变量,表示该变量从初始化后其|单变量直接存储|而不是引用)׃会改变,需要注意的是在使用其他cL供的 public ?/span> final 单变量的时候,q其他cL变了其定义ƈ重新~译Q用的cd重新~译前该值是不会改变的(参考: http://blog.csdn.net/daniel112/archive/2006/10/11/1330255.aspx Q。声明ؓ final 的对象变量表CZ旦初始化其引用不会改变?/span>
final 变量初始化化可以在声明时或构造函C完成?/span>
/**
声明时候直接初始化
*/
Public
final
String FINAL_STR
=
“final_str?
/**
在构造函C初始化?/span>
*/
Private
final
String FINAL_STR1;
Public MyFinalTest(){
FINAL_STR1
=
“asdfasd?
}
}
final c?/span>
定义?/span> final 的类表示该类不能被承,也就是说该类是一个功能设计完成,不在需要扩展的cR同时该成员Ҏ也对应默认标志ؓ final Q成员变量随定义而定?/span>
final Ҏ
定义?/span> final 的方法表CҎ不能被子c覆写( override Q?/span>
当一个请求发送到
servlet
容器的时候,容器先会请求的
url
减去当前应用上下文的
路径
作ؓ
servlet
的映?/span>
url
Q比如我讉K的是
http://localhost/test/aaa.html
Q我的应用上下文?/span>
test
Q容器会?/span>
http://localhost/test
LQ剩下的
/aaa.html
部分拿来?/span>
servlet
的映匹配。这个映匹配过E是有顺序的Q而且当有一?/span>
servlet
匚w成功以后Q就不会ȝ会剩下的
servlet
了(
filter
不同Q后文会提到Q。其匚w规则和顺序如下:
1.
_路径匚w。例子:比如
servletA
?/span>
url-pattern
?/span>
/test
Q?/span>
servletB
?/span>
url-pattern
?/span>
/*
Q这个时候,如果我访问的
url
?/span>
http://localhost/test
Q这个时候容器就会先
q行_路径匚wQ发?/span>
/test
正好?/span>
servletA
_匚wQ那么就去调?/span>
servletA
Q也不会ȝ会其他的
servlet
了?/span>
2.
最长\径匹配。例子:
servletA
?/span>
url-pattern
?/span>
/test/*
Q?/span>
servletB
?/span>
url-pattern
?/span>
/test/a/*
Q此时访?/span>
http://localhost/test/a
Ӟ容器会选择路径最长的
servlet
来匹配,也就是这里的
servletB
?/span>
3.
扩展匚wQ如?/span>
url
最后一D包含扩展,容器会Ҏ扩展选择合适的
servlet
。例子:
servletA
?/span>
url-pattern
Q?/span>
*.action
4.
如果前面三条规则都没有找C?/span>
servlet
Q容器会Ҏ
url
选择对应的请求资源。如果应用定义了一?/span>
default servlet
Q则容器会将h丢给
default servlet
Q什么是
default servlet
Q后面会Ԍ
?/span>
|
Ҏq个规则表,p很清楚的知道
servlet
的匹配过E,所以定?/span>
servlet
的时候也要考虑
url-pattern
的写法,以免出错?/span>
对于
filter
Q不会像
servlet
那样只匹配一?/span>
servlet
Q因?/span>
filter
的集合是一个链Q所以只会有处理的顺序不同,而不会出现只选择一?/span>
filter
?/span>
Filter
的处理顺序和
filter-mapping
?/span>
web.xml
中定义的序相同?/span>
?/span> web.xml 文g中,以下语法用于定义映射Q?/span>
l ?/span> ??/span> 开头和?/span> ?*?/span> l尾的是用来做\径映的?/span>
l 以前~ ?.?/span> 开头的是用来做扩展映射的?/span>
l ?? 是用来定?/span> default servlet 映射的?/span>
l 剩下的都是用来定义详l映的。比如: /aa/bb/cc.action
所以,Z么定?/span> ?*.action?/span> q样一个看h很正常的匚w会错Q因个匹配即属于路径映射Q也属于扩展映射Q导致容器无法判断?/span>
在装饰模式中的各个角色有Q?/p>
使用装饰模式主要有以下的优点Q?/font>
使用装饰模式主要有以下的~点Q?/strong>
׃使用装饰模式Q可以比使用l承关系需要较数目的cR用较的c,当然使设计比较易于进行。但是,在另一斚wQ用装饰模式会产生比用承关pL多的对象。更多的对象会得查错变得困难,特别是这些对象看上去都很相像?/p>
大多数情况下Q装饰模式的实现都比上面定义中给出的C意性实现要单。对模式q行化时需要注意以下的情况Q?/p>
Q?Q一个装饰类的接口必M被装饰类的接口相宏V?/p>
Q?Q尽量保持Component作ؓ一??c,不要把太多的逻辑和状态放在Componentc里?/p>
Q?Q如果只有一个ConcreteComponentc而没有抽象的Componentc(接口Q,那么Decoratorcȝ常可以是ConcreteComponent的一个子cR?/p>
Q?Q如果只有一个ConcreteDecoratorc,那么没有必要徏立一个单独的Decoratorc,而可以把Decorator和ConcreteDecorator的责dq成一个类?/span>
透明的装饰模?/font>
所谓透明是指对客LE序员来说是针对接口~程Q而不是具体的l承或实现类。引用R博士的《java与模式》的说法是:?span id="lblContent">必须永远把孙悟空的所有变化都当成孙悟I来对待Q而如果把老孙变成的雀儿当成雀儿,而不是老孙Q那p老孙骗了Q而这是不应当发生的?/span>?/p>
下面的做法是对的Q?/p>
半透明的装饰模?/font> 然而,Ua的装饰模式很难找到。装饰模式的用意是在不改变接口的前提下,增强所考虑的类的性能。在增强性能的时候,往往需要徏立新的公开的方法。即
便是在孙大圣的系l里Q也需要新的方法。比如齐天大圣类q没有飞行的能力Q而雀儿有。这意味着雀儿应当有一个新的fly()Ҏ?/p> q就D了大多数的装饰模式的实现都是"半透明"Qsemi-transparentQ的Q而不是完?透明"的。换a之,允许装饰模式改变接口Q?
增加新的Ҏ。即声明ConcreteDecoratorcd的变量,从而可以调用ConcreteDecoratorcM才有的方法: 齐天大圣接口Ҏ没有fly()q个ҎQ而雀儿接口里有这个方法?/p>
参考:
《java与模式?/p>
google搜烦Q?java decorator"