策略模式
返回值是固定的,中间逻辑不一样。例如从家出发去旅游,可以开车,做公交车,坐火车等。但是目的地是固定的。
阎宏博士的《JAVA与模式》一书中这样描述:中策略模式属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
如何到达目的地就是算法,开车、坐公交、坐火车等相当于对算法的封装,他们同属于一个范畴叫做出行方式,而出行人是算法的调用者,并且可以根据需求选择算法,这就是将算法和职责的分离。
这个模式涉及三个角色:
环境角色(Context):持有一个strategy的引用
抽象策略角色(Strategy):所有策略类的顶级父类或是接口,定义策略中的方法
具体策略角色(ConcreteStrategy):实现抽象策略中的方法,具体算法的实现者
代码示例:
List<Long> numbers = new ArrayList<Long>();
// todo 想list中添加内容
Collections.sort(numbers, new Comparator<Long>() {
//返回值是固定的
//0 、-1 、1
//0 、 >0 、<0
@Override
public int compare(Long o1, Long o2) {
//中间逻辑是不一样,泛型为Long、Object等比较方式不一样
return 0;
}
});
上面的例子中,Comparator就是策略的抽象,这里用了一个匿名内部类实现,而Collections.sort()方法测试集合工具类的一个职责——排序,而排序的逻辑由具体的策略来实现。
原型模式
首先要有一个原型,然后根据原型生成一个数据内容相同但是对象示例不同的实例,即两个完全不同的内存地址。孙悟空的变身术就是个很形象的例子。
对象拷贝时,类的构造函数是不会被执行,因为Object 类的 clone 方法的 原理是从内存中(具体的说就是堆内存)以二进制流的方式进行拷贝,重新分配一个内存块,那么构造函数也就没有被执行的必要了。
- 浅度克隆:当被克隆的类中有引用对象(String或Integer等包装类型除外)时,克隆出来的类中的引用变量存储的还是之前的内存地址,也就是说克隆与被克隆的对象是同一个。这样的话两个对象共享了一个私有变量,所有人都可以改,是一个种非常不安全的方式,在实际项目中使用还是比较少的。
- 深度克隆:可以重写clone方法,重新实现对象拷贝逻辑,例如字节码拷贝。注意:final 类型修饰的成员变量不能进行深度拷贝。以下是一个深度克隆的例子:
public Object clone(){
//深度克隆
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//return super.clone();//默认浅克隆,只克隆八大基本数据类型和String
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
TheGreatestSage copy = (TheGreatestSage)ois.readObject();
return copy;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally{
try {
bos.close();
oos.close();
bis.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
模板模式
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。通俗的说的就是有很多相同的步骤的,在某一些地方可能有一些差别适合于这种模式。这里以泡制一杯饮料的例子来说明,茶和coffee的泡制流程是固定的,只是原料和辅料不一样
public abstract class Bevegrage {
//不能被重写
public final void create(){
//1、把水烧开
boilWater();
//2、把杯子准备好、原材料放到杯中
pourInCup();
//3、用水冲泡
brew();
//4、添加辅料
addCoundiments();
}
public abstract void pourInCup();
public abstract void addCoundiments();
public void brew(){
System.out.println("将开水放入杯中进行冲泡");
};
public void boilWater(){
System.out.println("烧开水,烧到100度可以起锅了");
}
}
---
public class Coffee extends Bevegrage{
//原材料放到杯中
public void pourInCup() {
System.out.println("将咖啡倒入杯中");
}
//放辅料
public void addCoundiments() {
System.out.println("添加牛奶和糖");
}
}
---
public class Tea extends Bevegrage{
//原材料放到杯中
public void pourInCup() {
System.out.println("将茶叶放入杯中");
}
//放辅料
public void addCoundiments() {
System.out.println("添加蜂蜜");
}
}
SpringJDBC就是模板模式的一个应用,jdbc是一个规范,由数据库厂商自己去实现
- 加载驱动类DriverManager
- 建立连接
- 创建语句集(标准语句集、预处理语句集)(语句集? MySQL、Oracle、SQLServer、Access)
- 执行语句集
- 结果集ResultSet 游标