目录
一、装饰设计模式
1.1装饰设计模式
装饰设计模式的主要目的是修改已存在类的功能,假设有这么一个接口Creature,它定义了很多生物的一些方法,
public interface Creature {
public abstract void sleep();
public abstract void walk();
public abstract void eat();
public abstract void breath();
}
这个时候我们定义了一个灵长猿猴的类,实现Creature的接口,
public class Monkey implements Creature{
@Override
public void sleep() {
System.out.println("躺着休息");
}
@Override
public void walk() {
System.out.println("四只脚走路");
}
@Override
public void eat() {
System.out.println("素食荤食都吃");
}
@Override
public void breath() {
System.out.println("呼吸氧气");
}
}
如果我们此时想再定义人的类,人和灵长猿猴其他方法差不多,主要是行走的方式不同,如果我们再实现Creature的接口,对所有方法进行重写,毫无疑问这种办法效率很低下。
面对这种只需要改写类中个别方法,而大部分方法可以直接使用的情况,我们就要用到装饰者模式了,该模式设计步骤为:
- 编写一个类,实现与被包装类(Monkey类)相同的接口(Creature接口)
- 定义一个被包装类类型的变量(Monkey类型的变量)
- 定义构造方法,把被包装类的对象(Monkey类对象)注入,给被包装类变量赋值(Monkey类型的变量)
- 对于不需要改写的方法,调用原有的方法(Monkey类的方法)
- 对于需要改写的方法,写自己的代码(Human类的方法)
下面我们创建一个Human类,
public class Human implements Creature{
private Monkey monkey;
public Human(Monkey monkey){
this.monkey=monkey;
}
@Override
public void sleep() {
monkey.sleep();
}
@Override
public void walk() {
System.out.println("双脚独立行走");
}
@Override
public void eat() {
monkey.eat();
}
@Override
public void breath() {
monkey.breath();
}
}
可以看到我们仅仅重写了walk方法,其他方法都是调用传进来的Monkey对象的方法,这种设计模式称为装饰设计模式。
1.2适配器模式
装饰者模式的好处显而易见,但是也有个很明显的缺点,就是接口有多少种方法,你就要一个个地写多少种,虽然说不需要实现,只用调用被包装类对象的对应方法,但是该过程还是比较繁琐的。
适配器模式就解决了这个问题,该模式仅专注于需要修改的方法,不需要对不更改的方法进行重写,适配器模式步骤如下:
- 编写一个类,继承包装类适配器
- 定义一个被包装类类型的变量
- 定义构造方法,把被包装类的对象注入,给被包装类变量赋值
- 对于所有方法,调用被包装类原有的方法
这样就创建好了一个类的适配器,相当于把原来的类复制了一遍,然后我们新建一个类,直接继承适配器,这样就不用实现所有的方法,只需要重写个别方法即可。
二、事务
2.1事务的概述
事务是指访问并可能更新数据库中数据项的执行单元,可以是一条sql语句、一组sql语句或者整个程序,
组成这组操作的各个单元,要么全部成功,要么全部失败。事务是恢复和并发控制的基本单位。
例如假设用户a要向用户b转账100块钱,后台数据库更新会对应两条sql语句:
update account set money=money-100 where name='a';
update account set money=money+100 where name='b';
如果此时第一条语句更新失败,那么第二条语句理论来说也不应该更新成功,这就是事务的原子性。
数据库操作事务的命令DTL有以下几个:
- start transaction:开启事务
- Rollback:回滚事务
- Commit:提交事务
在mysql中是默认自动提交事务的,每条语句都处在单独的事务中。
我们使用代码模拟事务的原子性,首先在mysql中创建account表,有name和money两个属性,然后连接数据库进行money的更新。
package Transaction;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TransactionTest {
@Test
public void test1(){
Connection connection=null;
PreparedStatement ps=null;
try {
connection=DBUtils.getConnection();//获取数据库连接
connection.setAutoCommit(false);//设置事务不自动提交,相当于begin开启事务
ps=connection.prepareStatement("update account set money=money-500 where name='aaa'");
ps.executeUpdate();//执行sql更新语句
int i=10/0;//此处为异常,模拟程序中断
ps=connection.prepareStatement("update account set money=money+500 where name='bbb'");
ps.executeUpdate();//执行sql更新语句
connection.commit();//提交事务
} catch (Exception e) {
try {
connection.rollback();//如果发生了异常就回滚事务,保持事务的原子性
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
DBUtils.closeAll(null,ps,connection);//关闭数据库连接
}
}
}