设计模式

单例设计模式

只能有一个对象实例,通过私有化构造方法,并在类里创建一个静态对象实现,常用于工具类,节省重复创建对象,提高效率

通过构造方法私有化+静态方法 代替单例设计模式模式:占用内存多

//单例设计模式
public class Test3{
    public static void main(String[] args){
        Singleton1 s1 = Singleton1.getInstance();
        Singleton2 s2 = Singleton2.getInstance();
        s1.print();
        s2.print();
    }
}

//懒汉式
//占用内存时间短,但效率较低(延迟加载)
class Singleton1{
    private Singleton1(){};//私有化构造方法,外部无法创建对象
    private static Singleton1 s1;
    public static Singleton1 getInstance(){
        if(s1 == null){
            s1 = new Singleton1();
        }
        return s1;
    }
    public void print(){
        System.out.println("懒汉式测试方法");
    }
}

//饿汉式
//占用内存时间长,但效率高
class Singleton2{
    private Singleton2(){};
    private static Singleton2 s2 = new Singleton2();
    public static Singleton2 getInstance(){
        return s2;
    }
    public void print(){
        System.out.println("饿汉式测试方法");
    }
}

单例设计模式优化

//1.实现Serializable接口,允许序列化,方便还原单例状态
public class Singleton implements Serializable {
    private volidate static Singleton singleton = null;//使用volidate标记,每次取值从地址中取值,确保数据一致
    private Singleton(){
        if(singleton != null){
            //防止反射调用私有化构造方法
            throw new RuntimeException("此类对象为单例模式,已经被实例化");
        }
    }
    public static Singleton getSingleton(){
        if(singleton == null){
            //多线程访问安全,使用两次判断,防止第一次判断完就中断,没有加锁
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
    }
}

模板方法设计模式

定义一个操作中的算法骨架,而将一些可变部分的实现延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些步骤

public class Test8{
    public static void main(String[] args) {
        UserManager us = new UserManager();
        us.action("admin","add");
        us.action("test","del");
    }
}

abstract class BaseManager{
    public void action(String name,String method){
        if("admin".equals(name)){
            excute(method);
        }else{
            System.out.println("需要管理员权限");
        }
    }
    public abstract void excute(String method);
}


class UserManager extends BaseManager{
    public void excute(String method){
        //只实现具体的操作方法,验证层面在父类抽象类中
        if("add".equals(method)){
            System.out.println("执行了添加操作");
        }else if("del".equals(method)){
            System.out.println("执行了删除操作");
        }
    }
}

策略模式

定义一系列算法,将每一种算法封装起来并可以相互替换使用,策略模式让算法独立于使用它的客户应用而独立变化

public class Test9{
    public static void main(String[] args) {
        BaseService bs = new UserService();
        bs.setISave(new NetSave());//类实现借口,任然可以认为类型属于该接口
        bs.add("user");
    }
}

//定义一个接口
interface ISave{
    public void save(String data);
}

//对于不同的需求有不同的策略去实现
class FileSava implements ISave{
    public void save(String data){
        System.out.println("把数据存到文件中"+data);
    }
}

class NetSave implements ISave{
    public void save(String data){
        System.out.println("把数据存到网络上"+data);
    }
}

//定义一个抽象类用于不同的对象统一通过此处调用不同方法
abstract class BaseService{
    private ISave iSave;
    public void setISave(ISave iSave){
        this.iSave = iSave;
    }
    public void add(String data){
        iSave.save(data);
    }
}

class UserService extends BaseService{

}

简单工厂模式

由一个工厂对象决定创建出哪一种产品类的实例

public class Test10{
    public static void main(String[] args){
        //使用工厂模式降低耦合度,方便后期修改
        Product phone = ProductFactory.getProduct("phone");
        if(null!=phone){
            phone.work();
        }
    }
}

class ProductFactory{
    public static Product getProduct(String name){
        if("phone".equals(name)){
            return new Phone();
        }else if("computer".equals(name)){
            return new Computer();
        }else{
            return  null;
        }
    }
}

interface Product{
    public void work();
}

class Phone implements Product{
    public void work(){
        System.out.println("Phone is working...");
    }
}

class Computer implements Product{
    public void work(){
        System.out.println("Computer is working...");
    }
}

静态代理模式

为其他对象提供一种代理以控制对这个对象的访问,在访问对象时引入一定程度的间接性,以附加多种用途

public class Test11{
    public static void main(String[] args){
        IAction user = new UserAction();
        ActionProxy proxy = new ActionProxy(user);
        proxy.doAction();
    }
}

//代理
class ActionProxy implements IAction{
    private IAction target;//被代理的对象
    public ActionProxy(IAction target){
        this.target = target;
    }
    //执行操作
    public void doAction(){
        long startTime = System.currentTimeMillis();
        target.doAction();//执行真正的业务
        System.out.println("当前时间为:"+startTime);
    }
}

interface IAction{
    public void doAction();
}

class UserAction implements IAction{
    public void doAction(){
        System.out.println("开始工作了。。。");
    }
}

动态代理模式

/**
 * 接口
 */
interface Subject {
    public void shopping();
}

public class Person implements Subject{

    @Override
    public void shopping() {
        System.out.println("付款,买到心心念念的MacBook");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class CreateProxy implements InvocationHandler {
    private Object target;//被代理的对象

    //用于创建代理对象的方法
    public Object create(Object target){
        this.target = target;
        Object proxy = (Object) Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
        return proxy;
    }

    /**
     *
     * @param proxy 代理类对象
     * @param method 被代理对象的方法
     * @param args 方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("接项目做赚钱");
        System.out.println("上网上买");
        method.invoke(target,args);
        System.out.println("梦想成真");
        return null;
    }
}

public class ProxyTest {
    public static void main(String[] args) {
        CreateProxy cp = new CreateProxy();
        Subject person = new Person();
        Subject proxy  = (Subject) cp.create(person);
        proxy.shopping();//会调用invoke方法
    }
}

适配器模式

将一个类的接口转换成客户希望的另一个接口,用于使原来由于接口不兼容而不能一起工作的那些类可以一起工作

public class Test12{
    public static void main(String[] args){
        
        Animal dog = new Dog();
        dog.run();

        PowerA powerA = new PowerAImpl();
        PowerB powerB = new PowerBImpl();
        Adapter adapter = new Adapter(powerB);
        work(powerA);
        //work(powerB);若这样传则报错
        work(adapter);
    }
    public static void work(PowerA a){
        a.insert();
    }
}

/*第一种适配器*/
interface Animal{
    public void sing();
    public void cry();
    public void run();
    public void swim();
}

//适配器,当只需要实现一个方法的时候,避免子类多次重复空实现
abstract class AnimalFunction implements Animal{
    public void sing(){};
    public void cry(){};
    public void run(){};
    public void swim(){};
}

class Dog extends AnimalFunction{
    public void run(){
        System.out.println("the dog is running");
    }
}

/*第二种适配器*/
interface PowerA{
    public void insert();
}

class PowerAImpl implements PowerA{
    public void insert(){
        System.out.println("电源A开始工作");
    }
}
interface PowerB{
    public void insert();
}

class Adapter implements PowerA{
    private PowerB powerB;
    public Adapter(PowerB powerB){
        this.powerB = powerB;
    }
    public void insert(){
        powerB.insert();
    }
}
class PowerBImpl implements PowerB{
    public void insert(){
        System.out.println("电源B开始工作");
    }
}

装饰者模式

动态的给一个对象添加一些额外的职责,适用于子类过多,不能通过生成子类的方式进行扩充时

/**
 * Drink.java
**/
package decorator;

//被装饰者的基类(接口)
public interface Drink {
    float cost();//计算价格
    String description();//描述
}

/**
 * SoyaBeanMilk.java
 **/
package decorator;
//具体的被装饰者的类
public class SoyaBeanMilk implements Drink{


    @Override
    public float cost() {
        return 3;
    }

    @Override
    public String description() {
        return "纯豆浆";
    }
    
}

/**
 * Decorator.java
 **/
package decorator;

//装饰者的基类
public class Decorator implements Drink{

    private Drink drink;//要装饰的对象
    
    public Decorator(Drink drink) {
        this.drink = drink;
    }
    @Override
    public float cost() {
        return drink.cost();
    }

    @Override
    public String description() {
        return drink.description();
    }

}

/**
 * SugarDecorator.java
 **/
package decorator;

//具体的装饰类1
public class SugarDecorator extends Decorator{

    public SugarDecorator(Drink drink) {
        super(drink);
    }
    @Override
    public float cost() {
        return super.cost()+1.0f;
    }
    
    @Override
    public String description() {
        return super.description()+"+ 糖";
    }
}

//具体的装饰类2
public class EggDecorator extends Decorator{

    public EggDecorator(Drink drink) {
        super(drink);
    }
    @Override
    public float cost() {
        return super.cost()+2.0f;
    }
    
    @Override
    public String description() {
        return super.description()+"+ 蛋";
    }
}

//具体的装饰类3
public class BlackBeanDecorator extends Decorator{

    public BlackBeanDecorator(Drink drink) {
        super(drink);
    }
    @Override
    public float cost() {
        return super.cost()+2.0f;
    }
    
    @Override
    public String description() {
        return super.description()+"+ 黑豆";
    }
}

/**
 * Test.java
 **/
package decorator;

public class Test {

    public static void main(String[] args) {
        
        Drink drink = new SoyaBeanMilk();
        SugarDecorator sugar = new SugarDecorator(drink);
        EggDecorator egg = new EggDecorator(sugar);
        BlackBeanDecorator blackBean = new BlackBeanDecorator(egg);
        
        System.out.println("你点的内容是:" + blackBean.description());
        System.out.println("总价:"+blackBean.cost()+"元");
    }
}

观察者设计模式

package abserver;

/**
 * 被观察者接口
 */
public interface MessageSubject {
    //注册观察者
    public void registerObserver(Observer o);
    //移除观察者
    public void removeObserver(Observer o);
    //通知所有观察者
    public void notifyObsevers();
}

/**
 * 观察者接口
 */
public interface Observer {
    //更新消息
    public void update(String Message);
}

import java.util.ArrayList;
import java.util.List;

/**
 * 具体的被观察者
 */
public class Message implements MessageSubject{
    //维护的观察者列表
    private List<Observer> list = new ArrayList<>();
    //通知的消息
    private String message;

    public void setMessage(String message) {
        this.message = message;
        notifyObsevers();
    }

    @Override
    public void registerObserver(Observer o) {
        list.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        list.remove(o);
    }

    @Override
    public void notifyObsevers() {
        for (int i = 0; i < list.size(); i++) {
            Observer observer = list.get(i);
            observer.update(message);
        }
    }
}
/**
 * 具体的观察者
 */
public class User implements Observer{
    private String name;

    public User(String name){
        this.name = name;
    }

    @Override
    public void update(String Message) {
        System.out.println("["+name+"]"+"收到消息");
    }
}

//测试 
public class TestObserver {
    public static void main(String[] args) {
        Message message = new Message();

        Observer user1 = new User("Tom");
        Observer user2 = new User("Jack");
        Observer user3 = new User("Monkey");

        message.registerObserver(user1);
        message.registerObserver(user2);
        message.registerObserver(user3);

        message.setMessage("hello world");
        message.removeObserver(user1);
        message.setMessage("see you again");
    }
}

dao设计模式

DAO指的是Database Access Object,将数据库操作分为:

  • DAO接口
  • DAO接口实现类
  • 实体类:对应表中数据
  • 工具类:实现数据库的具体操作

文件命名规范:

  1. DAO接口类写在com.xx.dao包中
  2. 接口实现类写在com.xx.dao.impl包中
  3. 实体类写在com.xx.beans包中
  4. 工具类写在com.xx.util包中

数据库配置文件:

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/blog?useSSL=false
user = root
password = xxx

实体类:

package com.xm.beans;

import java.io.Serializable;

public class Student implements Serializable {
    private static final long serialVersionUID = -6861593743646559474L;
    private int id;
    private String stuName;
    private int age;
    private String course;
    private int score;

    public Student() {
    }

    public Student(int id, String stuName, int age, String course, int score) {
        this.id = id;
        this.stuName = stuName;
        this.age = age;
        this.course = course;
        this.score = score;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getStuName() {
        return stuName;
    }

    public void setStuName(String stuName) {
        this.stuName = stuName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getCourse() {
        return course;
    }

    public void setCourse(String course) {
        this.course = course;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", stuName='" + stuName + '\'' +
                ", age=" + age +
                ", course='" + course + '\'' +
                ", score=" + score +
                '}';
    }
}

工具类:

package hellojdbc.com.xm.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

/**
 * 封装MySQL操作工具类
 * 1. 注册驱动
 * 2. 获取连接
 * 3. 关闭连接
 * 4. 执行命令
 */
public class DbUtiles {
    //驱动名称
    private static String driver;
    //连接字符串
    private static String url;
    //用户名
    private static String userName;
    //密码
    private static String password;

    static {

        Properties properties = new Properties();
        //一种加载方法
        try {
            FileInputStream fis = new FileInputStream("src/database.properties");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //推荐使用这种方式,加载的是放在编译后.class文件夹中的properties文件
        InputStream is = DbUtiles.class.getClassLoader().getResourceAsStream("database.properties");

        try {
            properties.load(is);
            is.close();
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            userName = properties.getProperty("user");
            password = properties.getProperty("password");
        } catch (IOException e) {
            e.printStackTrace();
        }
        //注册驱动
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //获取连接
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url, userName, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    //关闭连接
    public static void closeAll(Connection connection, Statement statement,ResultSet resultSet){
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null){
            try{
                statement.close();
            }catch (SQLException e){
                e.printStackTrace();
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //执行命令(DML),需要使用可变长度数组作为参数,可以执行增删改
    public static int executeUpdate(String sql,Object...objects){
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        connection = getConnection();
        try {
            preparedStatement = connection.prepareStatement(sql);
            for(int i=0;i<objects.length;i++){
                preparedStatement.setObject(i+1,objects[i]);
            }
            int result = preparedStatement.executeUpdate();
            closeAll(connection,preparedStatement,null);
            return result;
        } catch (SQLException e) {
            e.printStackTrace();
            return 0;
        }
    }
}

接口类:

package hellojdbc.com.xm.dao;

import com.xm.beans.Student;

import java.util.List;

public interface StudentDao {
    //查找所有
    List<Student> findAll();
    //查找指定
    Student findById(int id);
    //更新
    void update(Student student);
    //删除
    void delete(int id);
    //添加
    void add(Student student);
}

接口实现类:

package com.xm.dao.impl;

import com.xm.beans.Student;
import hellojdbc.com.xm.dao.StudentDao;
import hellojdbc.com.xm.util.DbUtiles;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> findAll() {
        List<Student> students = new ArrayList<Student>();
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        connection = DbUtiles.getConnection();
        try {
            ps = connection.prepareStatement("select * from students");
            rs = ps.executeQuery();
            while (rs.next()){
                int id = rs.getInt("id");
                String stuName = rs.getString("stuName");
                int age = rs.getInt("age");
                String course = rs.getString("course");
                int score = rs.getInt("score");

                Student student = new Student(id,stuName,age,course,score);
                students.add(student);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtiles.closeAll(connection,ps,rs);
        }
        return students;
    }

    @Override
    public Student findById(int id) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        Student student = null;
        try {
            conn = DbUtiles.getConnection();
            ps = conn.prepareStatement("select * from students where id="+id);
            rs =  ps.executeQuery();
            if(rs.next()){
                String stuName = rs.getString("stuName");
                int age = rs.getInt("age");
                String course = rs.getString("course");
                int score = rs.getInt("score");
                student = new Student(id,stuName,age,course,score);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtiles.closeAll(conn,ps,rs);
            return student;
        }
    }

    @Override
    public void update(Student student) {
        Object[] params = {student.getAge(),student.getScore(),student.getId()};
        DbUtiles.executeUpdate("update students set age=?,score=? where id=?",params);
    }

    @Override
    public void delete(int id) {
        DbUtiles.executeUpdate("delete from students where id=?",id);
    }

    @Override
    public void add(Student student) {
        Object[] params = {student.getId(),student.getStuName(),student.getAge(),student.getCourse(),student.getScore()};
        DbUtiles.executeUpdate("insert into students values (?,?,?,?,?)",params);
    }
}

测试:

package hellojdbc;

import com.xm.beans.Student;
import com.xm.dao.impl.StudentDaoImpl;
import hellojdbc.com.xm.dao.StudentDao;

import java.util.List;
import java.util.Scanner;

public class DAOTest {
    public static void main(String[] args) {
        System.out.println("请选择操作:1查询 2添加 3更新 4删除");
        Scanner input = new Scanner(System.in);
        int choice = input.nextInt();
        StudentDao studentDao = new StudentDaoImpl();
        switch (choice){
            case 1:
                List<Student> students = studentDao.findAll();
                for(Student student:students){
                    System.out.println(student.toString());
                }
                break;
            case 2:
                System.out.println("请输入id");
                int id = input.nextInt();

                System.out.println("请输入姓名");
                String stuName = input.next();

                System.out.println("请输入年龄");
                int age = input.nextInt();

                System.out.println("请输入科目");
                String course = input.next();

                System.out.println("请输入分数");
                int score = input.nextInt();
                Student student = new Student(id,stuName,age,course,score);
                studentDao.add(student);
                System.out.println("添加成功!");
                break;
            case 3:
                System.out.println("要更新的编号:");
                int sid = input.nextInt();
                Student s = studentDao.findById(sid);
                if(s!=null){
                    System.out.println("输入分数");
                    int score1 = input.nextInt();
                    s.setScore(score1);
                    studentDao.update(s);
                    System.out.println("修改成功");
                }else{
                    System.out.println("没有此人");
                }
                break;
            case 4:
                System.out.println("请输入删除编号");
                int num = input.nextInt();
                studentDao.delete(num);
                System.out.println("删除成功");
                break;
            default:
                System.out.println("操作失误");
        }
    }
}