??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>
在装饰模式中的各个角色有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>
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());
}
}
}
]]>
]]>
1.什么时候?/b>
模拟cdQ?br />
2.CZ代码
在一个实际的目中,l部分用户增加了一个网l硬盘的服务。要对原来的用户注册Ҏq行扩展完成注册的时候给用户开通和l定|络盘的功能,又要保持原来注册的功能。我考虑使用decorator模式d一个装饰的用户理cL展原有的理cL实现?br />
* 用户理抽象接口QComponentQ?br /> */
public interface UserManager{
public void register(User user);
}
* 原有用户理具体c(Concrete ComponentQ?br /> */
public class DefaultUserManager implements UserManager{
public void register(User user){
//常规注册实现
}
}
* 用户理具体装饰cNetDiskManager(只有一个装饰对象的情况Q装饰类和具体装饰类合ƈ)
*/
public class NetdiskUserManager implements UserManager{
private UserManager userManager;
public NetdiskUserManager(UserManager userManager){
this.userManager = userManager;
}
public void register(User user){
bandingNetdisk(user);
userManager.register(user);
}
private void bandingNetdisk(User user){
//实现l定|络盘服务?/span>
}
}
3.在JDK-io包中的应?/b>
在jdk-io包中标准输入输出等相关cd都大量用了Decorator模式。如OutputStream与其相关子类的实现?br />
请参考:http://redlly.blog.hexun.com/2545654_d.html
4.使用装饰模式的优点和~点
5.使用装饰模式的讨?/b>
而下面的做法是不对的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"