程序设计最终将归结为"算法"和"设计模式",其中设计模式是我们进行良好程序设计的思想和"纲要";接下来本人将以通俗的实例来展示几种常用的设计模式,以及它们在java程序设计中需要注意的问题.
在此需要提醒一下,很多设计模式,只是思想上有稍微的区别,但是在程序设计(模板)中这种区别可能无法显著的表达出来,对于一个"靠天吃饭"的码农,我们了解它们的思想就已经足够了.
一.Singleton(单例模式):
单例模式,是一个神奇的模式,从狭隘的角度考虑,这种模式的实现,极度依赖于程序运行"容器"以及实例的生命周期,简单的归纳为:在指定"运行环境"中,任何时刻只能有一个实例存在.在java层面,单例和Classloader有必然关联关系,严格意义上说,一个classloader只能有一个单例的实例.
java序列化和反序列化、反射机制将有可能"打破"单例的设计,需要注意.
public class SingleTon implements Serializable{
private static final long serialVersionUID = 768457893059530646L;
/**
* 私有构造器,将可以避免通过"new Object()"方式创建对象
*/
private SingleTon(){
//检测instance是否已经初始化
//避免反射机制,导致的多例问题,通过反射机制仍然可以对私有构造函数进行操作
//---------------反射机制打破单例---
//Constructor[] constructors = SingleTon.class.getDeclaredConstructors();
//Constructor<SingleTon> c = constructors[0];
//c.setAccessible(true);
//SingleTon s2 = c.newInstance(null);
//-----------------------------------
if(instance != null){
return;
}
}
private static final SingleTon instance = new SingleTon();
public static SingleTon getInstance(){
return instance;
}
private void readObject(java.io.ObjectInputStream in) throws IOException{
//与writeObject对应,根据writeObject中write的顺序,进行read
//你可以决定,是否在此方法中,进行重置instance的属性值.
//this.age = in.readInt();
}
private void writeObject(ObjectOutputStream out) throws IOException{
//out.writeInt(this.age);
}
/**
* 严格单例,确保remote instance不会干扰单例模式,避免在反序列化过程中对单例的影响.
* @return
* @throws ObjectStreamException
*/
public Object readResolve() throws ObjectStreamException{
return instance;
}
}
二.Factory(工厂模式):
工厂模式,根据其实施手段的不同,分为"抽象工厂""静态工厂"等等,这些变种也是"万变不离其宗";工厂模式的精髓在于,让对象的创建过程和对象的消费者分离,生成的对象具有的特性与其交付给工厂方法的API参与而定..你可以把工厂模式,想象成现实生活中的工厂,你提交给工厂的订单参数,直接决定工厂为你生成的商品特性;再者,工厂就是为生产商品而生.
工厂模式,在我们的日常开发中,经常被使用到,或许这种模式已经被你踩在脚下,你却不能看清它的面目.
public class ConnectionFactory {
private String hostname;
private int port;
private List<Connection> pool = new LinkedList<Connection>();
private int corePoolSize;
private static final int DEFAULT_SIZE = 8;
public ConnectionFactory(String hostname,int port){
this(hostname,port,DEFAULT_SIZE);
}
public ConnectionFactory(String hostname,int port,int corePoolSize){
this.hostname = hostname;
this.port = port;
if(corePoolSize > 0){
this.corePoolSize = corePoolSize;
}
}
public synchronized Connection createConnection(){
if(pool.isEmpty()){
return new Connection(hostname, port);
}
return pool.remove(0);
}
/**
* static factory method
*/
public static Connection createConnection(String hostname,int port){
return new Connection(hostname, port);
}
public void returnSource(Connection connection){
if(pool.size() > corePoolSize){
return;
}
pool.add(0, connection);
}
static class Connection{
private String hostname;
private int port;
private Socket socket;
private boolean init;
public Connection(String hostname,int port){
this.hostname = hostname;
this.port = port;
}
public synchronized void connect() throws IOException{
if(init){
return;
}
socket = new Socket(hostname,port);
init = true;
}
public byte[] read(){return null;}
public void write(byte[] bytes){}
}
}
三.Builder(构建模式):
构建模式:如果创建一个对象需要多个环节,只有按照一定的"步骤"才能正确创建一个对象实例,那么这个过程就是构建.对此过程的封装,就是"构建模式".不过我怎么感觉“StringBuilder”是构建模式的体现呢?!
/**
* 构建一个sql语句
*/
public class QueryBuilder {
private Query query;
/**
* build模式,意味着一个"起始点"和"结束点"
* build过程起始点
* @param tableName
*/
private QueryBuilder(String tableName){
this.query = new Query(tableName);
}
public static QueryBuilder from(String tableName){
return new QueryBuilder(tableName);
}
/**
* 过程
* @param orderType
* @return
*/
public QueryBuilder order(String orderType){
query.setOrderType(orderType);
return this;
}
/**
* 过程
* @param key
* @param value
* @return
*/
public QueryBuilder addParam(String key,String value){
query.getParams().put(key, value);
return this;
}
/**
* "结束点",获得"构建"的结果
* @return
*/
public String build(){
StringBuilder sb = new StringBuilder();
sb.append("select * from ");
sb.append(query.getTableName());
Map<String,String> params = query.getParams();
for(Entry<String,String> entry : params.entrySet()){
sb.append(" ");
sb.append(entry.getKey());
sb.append("=");
sb.append(entry.getValue());
}
return sb.toString();
}
private class Query{
private String orderType;
private Map<String, String> params;
private String tableName;
public Query(String tableName){
this.tableName = tableName;
}
public String getOrderType() {
return orderType;
}
public void setOrderType(String orderType) {
this.orderType = orderType;
}
public String getTableName() {
return tableName;
}
public void setTableName(String tableName) {
this.tableName = tableName;
}
public Map<String, String> getParams() {
return params;
}
}
public static void main(String[] args){
QueryBuilder builder = QueryBuilder.from("user");
builder.order("desc")
.addParam("name", "zhangsan")
.addParam("status", "1");
String statement = builder.build();
}
}
四.Observer(观察者模式):
当一个对象的某个操作,会对其他对象带来"关联性"影响时,如果被影响者能够"获得通知",那么这种模式就为"观察者模式".在java中,已经提供了"观察者"模式的API,我们看看改如何使用它们.
观察者模式中需要"观察者"和"被观察者"2个角色.
public class ObserverSample {
static class TestObserable extends Observable{
private String name;
public TestObserable(){
super();
}
public TestObserable(String name){
super();
this.name = name;
}
public void update(String data){
//..
super.setChanged();
super.notifyObservers(data);//通知
super.clearChanged();
}
@Override
public String toString(){
return this.name == null ? super.toString() : this.name;
}
}
/**
* 观察者
*
*/
static class TestObserver implements Observer{
private String name;
public TestObserver(String name){
this.name = name;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(name + " find " + o.toString() + " changed");
System.out.println("changed data:" + arg.toString());
}
}
public static void main(String[] args){
TestObserver t1 = new TestObserver("t1");
TestObserver t2 = new TestObserver("t2");
TestObserable obserable = new TestObserable("observer");
//顺序很重要
obserable.addObserver(t1);
obserable.addObserver(t2);
obserable.update("update-test");
}
}
五.Chain(责任链模式)
chain,就是链,代码写起来也像"链条":如果一个"操作"需要被多个"处理器(processor)"依次顺序执行时,那么"责任链"模式,将会是最好的选择.不过,貌似 servlet中Filter是不是一种“责任链”的体现?!
public class PrinterSample {
private Printer printer;
public PrinterSample(Printer printer){
this.printer = printer;
}
public void printer(String data){
printer.execute(data);
}
static interface Printer {
public void execute(String data);
}
static abstract class AbstractPrinter implements Printer{
protected Printer nextPrinter;
protected AbstractPrinter(Printer next){
this.nextPrinter = next;
}
}
static class LengthPrinter extends AbstractPrinter{
protected LengthPrinter(Printer next) {
super(next);
}
@Override
public void execute(String data) {
System.out.println("length:" + data.length());
if(nextPrinter != null){
this.nextPrinter.execute(data);
}
}
}
static class HashcodePrinter extends AbstractPrinter{
protected HashcodePrinter(Printer next) {
super(next);
// TODO Auto-generated constructor stub
}
@Override
public void execute(String data) {
System.out.println("Hashcode:" + data.hashCode());
if(nextPrinter != null){
nextPrinter.execute(data);
}
}
}
static class ChecksumPrinter extends AbstractPrinter{
private static final Charset charset = Charset.forName("utf-8");
protected ChecksumPrinter(Printer next) {
super(next);
}
@Override
public void execute(String data) {
Adler32 checksum = new Adler32();
checksum.update(data.getBytes(charset));
System.out.println("Checksum:" + checksum.getValue());
if(nextPrinter != null){
nextPrinter.execute(data);
}
}
}
public static void main(String[] args){
//build chain:
ChecksumPrinter csp = new ChecksumPrinter(null);
HashcodePrinter hp = new HashcodePrinter(csp);
LengthPrinter lp = new LengthPrinter(hp);
//
PrinterSample sample = new PrinterSample(lp);
sample.printer("This is chain-model sample!");
}
}
六.Strategy(策略模式):
针对输入的数据,而采取相应的“算法”输出结果的方式。如下例子为,根据输入的key而输出相应的hash模的值。
public class HashStrategy {
public static long hashMode(Object key,int mod){
if(key == null){
throw new NullPointerException("key cant be null!");
}
if(key instanceof Number){
return NumberHashcode.hashcode(key) % mod;
}else{
return ObjectHashcode.hashcode(key) % mod;
}
}
static class NumberHashcode{
public static long hashcode(Object key) {
return ((Number)key).longValue();
}
}
static class ObjectHashcode{
public static long hashcode(Object key) {
return key.toString().hashCode() & 0x7FFFFFFF;
}
}
public static void main(String[] args){
System.out.println(HashStrategy.hashMode("test hashStrategy", 3));
System.out.println(HashStrategy.hashMode(12312412L, 3));
}
}
七.Proxy(代理模式):
代理模式,避免对实例方法的直接访问,而是使用代理对象来间接的去访问,这样一面可以在“实际调用”之前或者之后做一些补充性操作(比如参数变更,权限检测),另一面代理对象可以屏蔽掉实际实例的部分操作(让一些方法不可用)等。
public class ProxySample {
static interface Printer{
public void print(String value);
}
static class TimestampPrinter implements Printer{
@Override
public void print(String value) {
System.out.println("Value:" + value);
System.out.println("Timestamp:" + System.currentTimeMillis());
}
}
/**
* 静态代理类,通常和“被代理者”有着相同的接口列表,通常子类通过扩展接口的方式实现
*
*/
static class StaticProxy implements Printer {
//must "new Object"
private Printer printer = new TimestampPrinter();
public void print(String value){
System.out.println("Static proxy: before invoke...");
printer.print(value);
System.out.println("Static proxy: after invoke...");
}
}
static class DynamicProxy{
private Printer printer = new TimestampPrinter();//被代理者
private Printer proxy;//代理者
public DynamicProxy(){
proxy = (Printer)Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(), new Class[]{Printer.class}, new Invocation(printer));
}
public void print(String value) {
proxy.print(value);
}
}
static class Invocation implements InvocationHandler{
private Object obj;//被代理实例
public Invocation(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Dynamic proxy: before invoke");
Object result = method.invoke(obj, args);
System.out.println("Dynamic proxy: after invoke");
return result;
}
}
/**
* @param args
*/
public static void main(String[] args) {
DynamicProxy dproxy = new DynamicProxy();
dproxy.print("I am dynamic...");
StaticProxy sproxy = new StaticProxy();
sproxy.print("I am static...");
}
}
---先到此结束..