学一样东西,自己另外举个例子实现一遍,才能知道里面的原理.记录一下学习的几种基本的设计模式
文件结构
几种设计模式的文件结构如下图所示
源代码下载
源码下载
代理模式
说明
这里我举了一个网页渲染时使用代理延迟加载图片的例子,用线程的睡眠模拟延迟加载,hibernate的延迟加载就是用了代理模式实现
代理模式的主要应用:
- 远程代理,例如webservice
- 虚拟代理,html渲染
- 安全代理,控制真实对象的访问权限
spring的AOP就是用的代理模式的思想设计实现的
类图
代码
package codeDesign.proxy;
/**
* Created by kangbiao on 2015/11/22.
* 网页绘制接口,代理和被代理类均实现该接口
*/
public interface Draw {
/**
* 绘制图片,需要花很多时间,使用代理来绘制
* @param url
*/
void drawPicture(String url);
}
package codeDesign.proxy;
/**
* Created by kangbiao on 2015/11/22.
* 绘制html网页的类(该类会消耗很多时间)
*/
public class HtmlDraw implements Draw{
/**
* 该方法不耗时,不需要代理
* @param text
*/
public void drawText(String text) {
System.out.println("正在绘制文字:" + text);
}
/**
* 会消耗一定的时间,需要代理
* @param url
*/
@Override
public void drawPicture(String url) {
System.out.println("图片区域正在从远程加载图片");
try {
Thread.sleep(5000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("正在绘制图片:"+url);
}
}
package codeDesign.proxy;
/**
* Created by kangbiao on 2015/11/22.
* 图片绘制代理类
*/
public class ProxyDraw implements Draw {
HtmlDraw htmlDraw;
public ProxyDraw(){
this.htmlDraw=new HtmlDraw();
}
@Override
public void drawPicture(String url) {
System.out.println("代理先输出一张占位图片");
new Thread(new Runnable() {
@Override
public void run() {
htmlDraw.drawPicture("1.jpg");
System.out.println("代理去掉占位图片");
}
}).start();
}
}
package codeDesign.proxy;
/**
* Created by kangbiao on 2015/11/22.
* 代理模式测试类
*/
public class ProxyTest {
/**
* 该过程演示了网页的绘制过程,使用代理模式异步绘制网页上面的图片
* @param args
*/
public static void main(String[] args){
HtmlDraw htmlDraw=new HtmlDraw();
htmlDraw.drawText("文字1");
ProxyDraw proxyDraw=new ProxyDraw();
proxyDraw.drawPicture("1.jpg");
htmlDraw.drawText("文字2");
}
}
工厂模式
说明
最基础的设计模式
类图
代码
package codeDesign.factory;
/**
* Created by kangbiao on 2015/11/21.
*
*/
public class Tea {
private String sugar;
public void mixSugarTea(){
System.out.print("只有"+sugar);
}
public String getSugar()
{
return sugar;
}
public void setSugar(String sugar)
{
this.sugar = sugar;
}
}
package codeDesign.factory;
/**
* Created by kangbiao on 2015/11/21.
* 蓝茶
*/
public class BlueTea extends Tea{
public void mixSugarTea(){
System.out.print(super.getSugar()+"蓝茶");
}
}
package codeDesign.factory;
/**
* Created by kangbiao on 2015/11/21.
* 红茶
*/
public class BlackTea extends Tea{
public void mixSugarTea(){
System.out.print(super.getSugar()+"红茶");
}
}
package codeDesign.factory;
/**
* Created by kangbiao on 2015/11/21.
* 茶的工厂类
*/
public class TeaFactory {
public static Tea getTea(String teaType){
Tea tea;
switch (teaType){
case "black":
tea=new BlackTea();
break;
case "blue":
tea=new BlueTea();
break;
default:
tea=new Tea();
break;
}
return tea;
}
}
package codeDesign.factory;
/**
* Created by kangbiao on 2015/11/21.
* 工厂模式测试
*/
public class FactoryTest {
public static void main(String[] args){
Tea tea = TeaFactory.getTea("black");
tea.setSugar("红糖");
tea.mixSugarTea();
}
}
装饰器模式
说明
- 如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。
- 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。
- java的io流包就是使用的装饰器模式
类图
代码
package codeDesign.decorator;
/**
* Created by kangbiao on 2015/11/21.
* 汽车类
*/
public class Car {
public void showFunc(){
System.out.print("组装完毕");
}
}
package codeDesign.decorator;
/**
* Created by kangbiao on 2015/11/21.
* 汽车的功能类
*/
public class Function extends Car{
protected Car car;
public void addFuncs(Car car){
this.car=car;
}
public void showFunc(){
if (car!=null){
car.showFunc();
}
}
}
package codeDesign.decorator;
/**
* Created by kangbiao on 2015/11/21.
* 制动功能
*/
public class BrakingFunction extends Function{
public void showFunc(){
System.out.print("制动");
super.showFunc();
}
}
package codeDesign.decorator;
/**
* Created by kangbiao on 2015/11/21.
* ABS防抱死功能
*/
public class ABSFunction extends Function{
public void showFunc(){
System.out.print("ABS");
super.showFunc();
}
}
package codeDesign.decorator;
/**
* Created by kangbiao on 2015/11/21.
* 装饰模式测试
*/
public class DecoratorTest {
public static void main(String[] args){
Car car=new Car();
ABSFunction abs=new ABSFunction();
BrakingFunction braking=new BrakingFunction();
abs.addFuncs(car);
braking.addFuncs(abs);
braking.showFunc();
}
}
策略模式
说明
这里我结合了工厂模式,使得加密算法的选择逻辑不用暴露给客户端
Strategy中定义了公共算法的实现接口,然后通过多态在Context动态的创建不同的实现类的实例从而达到算法策略选择逻辑
简化单元测试,因为每一个具体的实现都在一个类里面,可以分开测试
减少了算法调用类和算法实现类之间的耦合
类图
代码
package codeDesign.strategy;
/**
* Created by kangbiao on 2015/11/21.
* 加密算法接口
*/
public interface EncryptStrategy {
/**
* 加密算法实现接口
* @param rawString
* @return
*/
String doEncrypt(String rawString);
}
package codeDesign.strategy;
/**
* Created by kangbiao on 2015/11/21.
* md5加密策略实现类
*/
public class MD5Strategy implements EncryptStrategy{
@Override
public String doEncrypt(String rawString) {
return "MD5("+rawString+")";
}
}
package codeDesign.strategy;
/**
* Created by kangbiao on 2015/11/21.
* SHA1加密实现类
*/
public class SHA1Strategy implements EncryptStrategy {
@Override
public String doEncrypt(String rawString) {
return "SHA1("+rawString+")";
}
}
package codeDesign.strategy;
/**
* Created by kangbiao on 2015/11/21.
* 加密上下文维护类,客户端调用类
*/
public class EncryptContext {
private EncryptStrategy encryptStrategy;
public final static byte MD5=0;
public final static byte SHA1=1;
/**
* 这里实现用工厂模式实现自动装载不同的类
* @param method
*/
public EncryptContext(Byte method){
switch (method){
case MD5:
this.encryptStrategy=new MD5Strategy();
break;
case SHA1:
this.encryptStrategy=new SHA1Strategy();
break;
default:
break;
}
}
public String doEncrypt(String rawString){
return encryptStrategy.doEncrypt(rawString);
}
}
package codeDesign.strategy;
/**
* Created by kangbiao on 2015/11/21.
* 策略模式测试类
*/
public class EncryptTest {
public static void main(String[] args){
EncryptContext encryptContext=new EncryptContext(EncryptContext.MD5);
String result=encryptContext.doEncrypt("123456");
System.out.print(result);
}
}