年末技术总结之设计模式 创建型模式

1,马上农历年末了,在这一年中,到底学习了神马有用的技术知识,所谓温故知新,打算写下来,总结和提高一下,大致想这么写,看时间而定;

2,首先就是设计模式的回顾,这个比较常用,大到设计系统,小到做需求,用到的频率都蛮高的,设计模式大致分成3类,创建型,结构型,行为型;创建型比较简单,这里先复习这个;

3,先分开回顾,结合在工作当中碰到的问题,自己重新理解下,有神马不对的,各位屌丝兄弟指出来,共同进步;

3.1 单例模式

  个人理解是为了保证数据的一致性使用这个模式;

类别 详细
简介 保证一个类只有一个实例,并提供一个访问实例的全局访问点,避免不一致的情况发生;
参考 http://www.cnblogs.com/whgw/archive/2011/10/05/2199535.html
实例分析
package com.lifc.year.end.design.pattern.creation.singleton;

public class Singleton {
    
    private static Singleton instance=new Singleton();
    
    private String name;
    
    
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    private Singleton()
    {
        
    }

    public static Singleton getInstance()
    {
        return instance;
    }
}


package com.lifc.year.end.design.pattern.creation.singleton;

public class Client {

    /**
     * 创建时间: 2013-1-28 上午11:00:07
     * 创建人:cutter.li
     * 参数: 
     * 返回值: void
     * 方法描述 :
    */
    public static void main(String[] args) {

        Singleton s1=Singleton.getInstance();
        s1.setName("cutter.li");
        System.out.println(s1.getName());
        Singleton s2=Singleton.getInstance();
        System.out.println(s2.getName());
        
        System.out.println("单例吗?"+s1.equals(s2));
        
        
    }

}

 

说明
单例的实现方式分成三类:1,饱汉式,我写的一个简单例子就是这种形式实现的;2,饿汉式,需要的时候再创建唯一实例;3,注册式,spring里配置一个单例的对象使用的就是这种方式;

个人工作当中用到的单例模式,主要是Servlet,所有的servlet都是单例的,工作方式如下:

Servlet容器默认是采用单实例多线程的方式处理多个请求的:


1.      当web服务器启动的时候(或客户端发送请求到服务器时),Servlet就被加载并实例化(只存在一个Servlet实例);


2.      容器初始化Servlet。主要就是读取配置文件(例如tomcat,可以通过servlet.xml的<Connector>设置线程池中线程数目,初始化线程池;通过web.xml,初始化每个参数值等等);


3.      当请求到达时,Servlet容器通过调度线程(Dispatchaer Thread)调度它管理下的线程池中等待执行的线程(Worker Thread)给请求者;


4.      线程执行Servlet的service方法;


5.      请求结束,放回线程池,等到被调用;

 

 

3.2  原型模式

  通过复制来创建对象;

类别 详细
简介 通过给出一个原型对象来指明所有要创建的对象类型,然后用复制这个原型对象来创建更多的对象。
参考 http://www.cnblogs.com/java-my-life/archive/2012/04/11/2439387.html
实例分析

package com.lifc.year.end.design.pattern.creation.prototype;

import java.io.Serializable;

public class Stick implements Serializable {

private static final long serialVersionUID = 7469022367218217983L;

final float rate = 0.2f;

private String name;

private float height = 1.5f;

private float radius = 0.1f;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public float getHeight() {
return height;
}

public void setHeight(float height) {
this.height = height;
}

public float getRadius() {
return radius;
}

public void setRadius(float radius) {
this.radius = radius;
}

public void zoom() {

this.height *= (1 + rate);
this.radius *= (1 + rate);
}

public void lessen() {
this.height *= (1 - rate);
this.radius *= (1 - rate);
}

@Override
public String toString() {
return getName()+",长---"+getHeight()+"米--- ,直径---"+getRadius();
}

}


package com.lifc.year.end.design.pattern.creation.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

public class Monkey implements Cloneable, Serializable {

private static final long serialVersionUID = 8983410453711474678L;

private String name;

private String hat;

private Stick jiGuBang;

private String cloth;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getHat() {
return hat;
}

public void setHat(String hat) {
this.hat = hat;
}

public Stick getJiGuBang() {
return jiGuBang;
}

public void setJiGuBang(Stick jiGuBang) {
this.jiGuBang = jiGuBang;
}

public String getCloth() {
return cloth;
}

public void setCloth(String cloth) {
this.cloth = cloth;
}

@Override
protected Object clone() throws CloneNotSupportedException {

return (Monkey)super.clone();
}

public Monkey deepClone()
{
ByteArrayOutputStream os=new ByteArrayOutputStream();
try {
ObjectOutputStream oos=new ObjectOutputStream(os);
oos.writeObject(this);
InputStream is=new ByteArrayInputStream(os.toByteArray());
ObjectInputStream ois=new ObjectInputStream(is);

return (Monkey)ois.readObject();

} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

return null;
}

}

package com.lifc.year.end.design.pattern.creation.prototype;

public class Client {
public static void main(String[] args) {

Stick stick=new Stick();
stick.setName("如意金箍棒");

Monkey monkey=new Monkey();
monkey.setName("孙悟空");
monkey.setCloth("裂地穿云甲");
monkey.setHat("凤劈紫金冠");
monkey.setJiGuBang(stick);

System.out.println("真身: "+monkey.getName()+","+monkey.getHat()+" ,"+monkey.getCloth()+" ,"+monkey.getJiGuBang().toString());


try {
Monkey fenshen=(Monkey)monkey.clone();


System.out.println("分身1:浅复制 "+fenshen.getName()+","+fenshen.getHat()+" ,"+fenshen.getCloth()+" ,"+fenshen.getJiGuBang().toString());

} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

Monkey fenshen2=monkey.deepClone();
fenshen2.getJiGuBang().zoom();
System.out.println("分身2:深复制 "+fenshen2.getName()+","+fenshen2.getHat()+" ,"+fenshen2.getCloth()+" ,"+fenshen2.getJiGuBang().toString());

System.out.println("真身: "+monkey.getName()+","+monkey.getHat()+" ,"+monkey.getCloth()+" ,"+monkey.getJiGuBang().toString());
}

}

 

 

 

说明
实例通过孙悟空扯几根毛身外化身的例子来反映原型模式的应用;

克隆必须满足的条件:
a.对任何的对象x,都有:x.clone() != x,即克隆对象与原对象不是同一个对象。
b.对任何的对象x,都有:x.clone().getClass() == x.get getClass(),即克隆对象与原对象的类型是一样的。 c.如果对象x的equals()方法定义恰当的话,那么x.clone().equals(x)应当是成立的。
在java中实现clone()应该满足这三个条件。

浅复制:复制了值类型对象,对于引用类型对象,只复制了引用,它指向原来引用的对象。Java中clone为浅复制。
深复制:对值类型和引用类型的对象都生成一份新的拷贝. Java中可以通过串行化来进行深复制,前提是对象以及对象内部所引用的对象都是可串行化的,否则需要考虑将那些不可串行化的对象可否设为transient,排除 在复制过程之外。

适用于创建对象比较困难的环境;

 

3.3  建造者模式

  表示和构建分离;

类别 详细
简介 将一个对象的表示和构建分离,使得同样的构建过程可以创建不同的表示;
实例分析

package com.lifc.year.end.design.pattern.creation.build;

public interface Builder {

public void installCPU();

public void installMemory();

public void installMotherBoard();

public void installHardDisk();

public void installMonitor();

public void installSystem();
}

package com.lifc.year.end.design.pattern.creation.build;

public class TableBuilder implements Builder {

@Override
public void installCPU() {
System.out.println("安装Inter I3 处理器");

}

@Override
public void installMemory() {
System.out.println("安装DDR3 8G 内存");

}

@Override
public void installMotherBoard() {
System.out.println("安装最新的技嘉主板 ");

}

@Override
public void installHardDisk() {
System.out.println("安装三星固态硬盘 ");
}

@Override
public void installMonitor() {
System.out.println("安装20寸液晶显示器 ");

}

@Override
public void installSystem() {
System.out.println("安装win8系统");

}

}

package mode.creation.build;

public class Director {

private Builder builder;

public Director(Builder builder)
{
this.builder=builder;
}


public void build()
{
System.out.println("安装台式机的过程....");
System.out.println("1,把主板装到主机箱里...");
builder.installMotherBoard();
System.out.println("2,把处理器装到主板上...");
builder.installCPU();
System.out.println("3,把内存装到主板上...");
builder.installMemory();
System.out.println("4,把硬盘装到机箱里...");
builder.installHardDisk();
System.out.println("5,装好机箱,连接显示器...");
builder.installMonitor();
System.out.println("6,接上电源安装系统...");
builder.installSystem();

}
}

package mode.creation.build;

import mode.creation.build.Director;

public class Client {

public static void main(String[] args) {

Director director=new Director(new TableBuilder());

director.build();

}

}

 


 

说明
实例装配台式机的例子来展示建造者模式;

在工作当中,比如封装jdbc的底层操作的时候,使用了这个模式,把相同的操作代码,比如打开连接和关闭连接,验证参数的代码放到方法当中,不同的执行sql,获取结果集的操作写成抽象方法,放到子类实现,访问过程独立一些基本代码;

 

 

3.4 工厂方法模式

  创建对象延迟到之类;

  

类别 详细
简介 定义一个用户创建对象的接口,让子类决定实例化哪个类,工厂方法使得一个类的实例化延迟到子类中来;
参考 http://blog.csdn.net/yuan22003/article/details/6709649
实例分析

手写例子:最近想买个电脑,考虑dell和apple,利用工厂方法模式模拟一下得到电脑的过程如下:
package com.lifc.year.end.design.pattern.creation.factorymethod;

public interface Computer {

public void self();

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public class Dell implements Computer {

@Override
public void self() {

System.out.println("dell 电脑,inter 芯片,高端享受···");

}

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public class Apple implements Computer {

@Override
public void self() {

System.out.println(" apple 电脑,jobs设计,体验极致···");

}

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public interface ComputerFactory {

public Computer getComputer();

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public class AppleComputerFactory implements ComputerFactory {

@Override
public Computer getComputer() {
return new Apple();
}

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public class DellComputerFactrory implements ComputerFactory {

@Override
public Computer getComputer() {
return new Dell();
}

}

package com.lifc.year.end.design.pattern.creation.factorymethod;

public class Client {

/**
* 创建时间: 2013-1-28 上午11:29:47
* 创建人:cutter.li
* 参数:
* 返回值: void
* 方法描述 :
*/
public static void main(String[] args) {

System.out.println(" I want by a apple Computer ...");

ComputerFactory computerFactory=new AppleComputerFactory();

Computer apple=computerFactory.getComputer();

System.out.println(" get a computer ,it is information ...");

apple.self();

}

}

 


 

说明
总的感觉是面对需求变更,1,扩展容易,不会影响之前的功能,但是需要创建太多的类,2,需要变更客户端代码;(如果不想修改代码,可以通过反射机制,修改配置文件)

 

 

3.5 抽象工厂模式

  创建一些列产品族的模式;

类别 详细
简介 提供一个创建一系列相关或者相互依赖对象的接口,无需制定他们的具体类;
参考 比较好的例子:http://gengu.iteye.com/blog/1125260
实例分析

手写例子:组装电脑,使用不同平台的cup,主板,内存等的例子:


 

说明
可灵活适应变化,但是类增加的太多了

 

 

 

 

4,横向对比

  五种创建型模式,各有优劣,分别适合不同的场景。

 

 

 

 

 

 

posted @ 2013-02-04 18:13  李福春  阅读(1668)  评论(2编辑  收藏  举报