设计模式

2021-04-19  本文已影响0人  睡不醒的大橘

一、设计模式的原则

1.单一职责原则

2.开闭原则

3.里氏替换原则

4.依赖倒置原则

5.接口隔离原则

6.合成复用原则

7.迪米特法则

二、设计模式的分类

创建型模式

1. 工厂模式(Factory Method)

interface food{}

class A implements food{}
class B implements food{}
class C implements food{}
public class StaticFactory {
    private StaticFactory(){}
    
    public static food getA(){  return new A(); }
    public static food getB(){  return new B(); }
    public static food getC(){  return new C(); }
}

class Client{
    //客户端代码只需要将相应的参数传入即可得到对象
    //用户不需要了解工厂类内部的逻辑。
    public void get(String name){
        food x = null ;
        if ( name.equals("A")) {
            x = StaticFactory.getA();
        }else if ( name.equals("B")){
            x = StaticFactory.getB();
        }else {
            x = StaticFactory.getC();
        }
    }
}

2. 抽象工厂模式(Abstract Factory)

interface food{}

class A implements food{}
class B implements food{}

interface produce{ food get();}

class FactoryForA implements produce{
    @Override
    public food get() {
        return new A();
    }
}
class FactoryForB implements produce{
    @Override
    public food get() {
        return new B();
    }
}
public class AbstractFactory {
    public void ClientCode(String name){
        food x= new FactoryForA().get();
        x = new FactoryForB().get();
    }
}

3. 建造者模式(Builder)

public class Builder {

    static class Student{
        String name = null ;
        int number = -1 ;
        String sex = null ;
        int age = -1 ;
        String school = null ;
     //构建器,利用构建器作为参数来构建Student对象
        static class StudentBuilder{
            String name = null ;
            int number = -1 ;
            String sex = null ;
            int age = -1 ;
            String school = null ;
            public StudentBuilder setName(String name) {
                this.name = name;
                return  this ;
            }

            public StudentBuilder setNumber(int number) {
                this.number = number;
                return  this ;
            }

            public StudentBuilder setSex(String sex) {
                this.sex = sex;
                return  this ;
            }

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

            public StudentBuilder setSchool(String school) {
                this.school = school;
                return  this ;
            }
            public Student build() {
                return new Student(this);
            }
        }

        public Student(StudentBuilder builder){
            this.age = builder.age;
            this.name = builder.name;
            this.number = builder.number;
            this.school = builder.school ;
            this.sex = builder.sex ;
        }
    }

    public static void main( String[] args ){
        Student a = new Student.StudentBuilder().setAge(13).setName("LiHua").build();
        Student b = new Student.StudentBuilder().setSchool("sc").setSex("Male").setName("ZhangSan").build();
    }
}

4. 原型模式(Protype)

深拷贝
public class Prototype implements Cloneable{

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    protected Object clone()   {
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }finally {
            return null;
        }
    }

    public static void main ( String[] args){
        Prototype pro = new Prototype();
        Prototype pro1 = (Prototype)pro.clone();
    }
}

5. 单例模式(Singleton)

1). 饿汉法
public class Singleton {  
    private static Singleton instance = new Singleton();  

    private Singleton (){}  

    public static Singleton getInstance() {  
      return instance;  
    }  

}  
2). 单线程写法
public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
      return instance;  
    }  
} 
3). 考虑线程安全的写法
public class Singleton {  
    private static Singleton instance;  

    private Singleton (){}  

    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
      return instance;  
    }  

}  
4). 兼顾线程安全和效率的写法

双重校验锁

public class Singleton {  
    private volatile static Singleton singleton;  

    private Singleton (){}  

    public static Singleton getSingleton() {  
      if (singleton == null) {  
            synchronized (Singleton.class) {  
                 if (singleton == null) {  
                        singleton = new Singleton();  
                  }  
            }  
        }  
      return singleton;  
    }  
}  
5). 静态内部类法
//Initialization on Demand Holder
public class Singleton{
       private  Singleton(){
       }

       private static class HolderClass{
              private final static Singleton  instance = new Singleton();
       }

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

       public  static void main(String args[]){
              Singleton  s1, s2;
        s1 = Singleton.getInstance();
              s2 = Singleton.getInstance();
              System.out.println(s1==s2);
       }
}
6). 枚举写法
public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}  

结构型模式

1. 适配器模式(Adapter)

1). 类适配器模式
public interface Ps2 {
    void isPs2();
}

public interface Usb {
    void isUsb();
}

public class Usber implements Usb {
    @Override
    public void isUsb() {
        System.out.println("USB口");
    }
}

public class Adapter extends Usber implements Ps2 {
    @Override
    public void isPs2() {
        isUsb();
    }
}

public class Clienter {
    public static void main(String[] args) {
        Ps2 p = new Adapter();
        p.isPs2();
    }
}
2). 对象适配
public class Adapter implements Ps2 {
    private Usb usb;
    public Adapter(Usb usb){
        this.usb = usb;
    }
    @Override
    public void isPs2() {
        usb.isUsb();
    }
}

public class Clienter {
    public static void main(String[] args) {
        Ps2 p = new Adapter(new Usber());
        p.isUsb();
    }
}
3). 接口适配器模式
public interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
    void f();
}

public abstract class Adapter implements A {
    public void a(){}
    public void b(){}
    public void c(){}
    public void d(){}
    public void e(){}
    public void f(){}
}

public class Ashili extends Adapter {
    public void a(){
        System.out.println("实现A方法被调用");
    }
    public void d(){
        System.out.println("实现d方法被调用");
    }
}

public class Clienter {
    public static void main(String[] args) {
        A a = new Ashili();
        a.a();
        a.d();
    }
}

2.装饰模式

//基础接口
public interface Component {
    
    public void biu();
}
//具体实现类
public class ConcretComponent implements Component {

    public void biu() {
        
        System.out.println("biubiubiu");
    }
}
//装饰类
public class Decorator implements Component {

    public Component component;
    
    public Decorator(Component component) {
        
        this.component = component;
    }
    
    public void biu() {
        
        this.component.biu();
    }
}
//具体装饰类
public class ConcreteDecorator extends Decorator {

    public ConcreteDecorator(Component component) {

        super(component);
    }

    public void biu() {
        
        System.out.println("ready?go!");
        this.component.biu();
    }
}
//使用装饰器
  Component component = new ConcreteDecorator(new ConcretComponent());
  component.biu();

  //console:
  ready?go!
  biubiubiu

3. 代理模式

1).静态代理
/**
 * 接口
 */
public interface IUserDao {

    void save();
}
/**
 * 接口实现
 * 目标对象
 */
public class UserDao implements IUserDao {
    public void save() {
        System.out.println("----已经保存数据!----");
    }
}
/**
 * 代理对象,静态代理
 */
public class UserDaoProxy implements IUserDao{
    //接收保存目标对象
    private IUserDao target;
    public UserDaoProxy(IUserDao target){
        this.target=target;
    }

    public void save() {
        System.out.println("开始事务...");
        target.save();//执行目标对象的方法
        System.out.println("提交事务...");
    }
}
/**
 * 测试类
 */
public class App {
    public static void main(String[] args) {
        //目标对象
        UserDao target = new UserDao();

        //代理对象,把目标对象传给代理对象,建立代理关系
        UserDaoProxy proxy = new UserDaoProxy(target);

        proxy.save();//执行的是代理的方法
    }
}
2). 动态代理
/**
 * 创建动态代理对象
 * 动态代理不需要实现接口,但是需要指定接口类型
 */
public class ProxyFactory{

    //维护一个目标对象
    private Object target;
    public ProxyFactory(Object target){
        this.target=target;
    }

   //给目标对象生成代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开始事务2");
                        //执行目标对象方法
                        Object returnValue = method.invoke(target, args);
                        System.out.println("提交事务2");
                        return returnValue;
                    }
                }
        );
    }

}
/**
 * 测试类
 */
public class App {
    public static void main(String[] args) {
        // 目标对象
        IUserDao target = new UserDao();
        // 【原始的类型 class cn.itcast.b_dynamic.UserDao】
        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.save();
    }
}

行为型模式

1. 模板方法模式

  1. 保护抽象类中定义算法顺序的方法不被子类修改。
  2. 分离可变及不可变部分,让子类自己决定可变部分的实现。
  3. 让算法的具体实现对子类开放,对其他类关闭。
package com.singland.dp.template;

public abstract class DriveTemplate {
    
    public final void drive() {
        openDoor();
        startEngine();
        gear();
        go();
        if (music()) {
            mp3();
        }
        brake();
        stop();
    }
    
    protected abstract void openDoor();
    
    protected void startEngine() {
        System.out.println("engine started !");
    }
    
    protected abstract void gear();
    
    protected void go() {
        System.out.println("running...");
    }
    
    private void mp3() {
        System.out.println("music is good");
    }
    
    protected boolean music() {
        return false;
    }
    
    protected abstract void brake();
    
    protected void stop() {
        System.out.println("stopped !");
    }
}

package com.singland.dp.template;

public class SuzukiScross extends DriveTemplate {
    
    @Override
    protected void openDoor() {
        System.out.println("keyless entry");
    }

    @Override
    protected void gear() {
        System.out.println("gear with hand");
    }

    @Override
    protected void brake() {
        System.out.println("brake with foot");
    }

    @Override
    protected boolean music() {
        return true;
    }
}
package com.studentinfomgt.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;

public abstract class JdbcTemplate2 {
    
    @Autowired
    private DataSource dataSource;
    
    private Connection connection;
    
    protected PreparedStatement statement;
    
    protected ResultSet resultSet;
    
    public final void dbOperation(String sql, Object entity) throws SQLException {
        getStatement(sql);
        crud(entity);
        releaseResources();
    }

    protected void getStatement(String sql) throws SQLException {
        connection = dataSource.getConnection();
        this.statement = connection.prepareStatement(sql);
    }
    
    protected abstract void crud(Object entity) throws SQLException;
    
    private void releaseResources() throws SQLException {
        if (resultSet != null)
            resultSet.close();
        if (statement != null)
            statement.close();
        if (connection != null)
            connection.close();
    }
}
package com.studentinfomgt.dao;

import java.sql.SQLException;

import com.studentinfomgt.pojo.Student;

public class JdbcCreateEntity extends JdbcTemplate2 {
    
    @Override
    protected void crud(Object entity) throws SQLException {
        Student student = (Student) entity;
        statement.setString(1, student.getId());
        statement.setString(2, student.getStudentNumber());
        statement.setString(3, student.getFirstName());
        statement.setString(4, student.getLastName());
        statement.setString(5, student.getGender());
        statement.setInt(6, student.getAge());
        statement.setString(7, student.getClassName());
        statement.setString(8, student.getMajor());
        statement.execute();
    }
}

2. 访问者模式

  1. 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
  2. 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  3. 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
  4. 具体元素(ConcreteElement)角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
/**
 * 访问者接口
 */
public interface IVisitor {

    void visit(FreeCourse freeCourse);

    void visit(CodingCourse codingCourse);
}


/**
 * 访问者的具体实现
 */
public class Visitor implements IVisitor {
    @Override
    public void visit(FreeCourse freeCourse) {
        System.out.println("free course: " + freeCourse.getName());
    }

    @Override
    public void visit(CodingCourse codingCourse) {
        System.out.println("coding course: " + codingCourse.getName() + " price: " + codingCourse.getPrice());
    }
}

/**
 * 抽象类,课程
 */
public abstract class Course {

    private String name;

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

    public String getName() {
        return name;
    }

    abstract void accept(IVisitor visitor);

}

/**
 * 具体的实体类,免费课程
 */
public class FreeCourse extends Course {


    @Override
    void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

/**
 * 具体的实现类,实战课程
 */
public class CodingCourse extends Course {

    private int price;

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    @Override
    void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}


/**
 * 测试类
 */
public class App {

    @Test
    public void test(){
        //初始化容器
        List<Course> courses = new ArrayList<>();

        //构建课程实现
        FreeCourse freeCourse = new FreeCourse();
        freeCourse.setName("SpringMVC.");

        CodingCourse codingCourse = new CodingCourse();
        codingCourse.setName("Java design pattern.");
        codingCourse.setPrice(299);

        //装填
        courses.add(freeCourse);
        courses.add(codingCourse);

        //访问
        for (Course course : courses) {
            course.accept(new Visitor());
        }
    }
}

  1. 扩展性好。能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。
  2. 复用性好。可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。灵活性好。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可相对自由地演化而不影响系统的数据结构。
  3. 符合单一职责原则。访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。
  1. 增加新的元素类很困难。在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。
  2. 破坏封装。访问者模式中具体元素对访问者公布细节,这破坏了对象的封装性,具体元素变更比较麻烦。违反了依赖倒置原则。
  3. 访问者模式依赖了具体类,而没有依赖抽象类。
上一篇下一篇

猜你喜欢

热点阅读