设计模式之为什么要学好设计模式

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
云数据库 RDS MySQL Serverless,价值2615元额度,1个月
简介: 设计模式之为什么要学好设计模式

1 回顾软件设计原则

文章推荐IDEA快速构建UML类图:https://blog.csdn.net/ZGL_cyy/article/details/118278233


不用设计模式并非不可以,但是用好设计模式能帮助我们更好地解决实际问题,设计模式最重要的是解耦。设计模式天天都在用,但自己却无感知。我们把设计模式作为一个专题,主要是学习设计模式是如何总结经验的,把经验为自己所用。学设计模式也是锻炼将业务需求转换技术实现的一种非常有效的方式。

设计原则 解释
开闭原则 对扩展开放,对修改关闭
依赖倒置原则 通过抽象使各个类或者模块不相互影响,实现松耦合。
单一职责原则 一个类、接口、方法只做一件事。
接口隔离原则 尽量保证接口的纯洁性,客户端不应该依赖不需要的接口。
迪米特法则 又叫最少知道原则,一个类对其所依赖的类知道得越少越好。
里氏替换原则 子类可以扩展父类的功能但不能改变父类原有的功能。
合成复用原则 尽量使用对象组合、聚合,而不使用继承关系达到代码复用的目的。

2 设计模式总览

写出优雅的代码以下是超级乱的代码

    public void setExammingForm(ExammingForm curForm,String parameters)throws BaseException {                                                                             
              ...
        JSONObject jsonObj = new JSONObject(parameters);
        //试卷主键                                                 
        if(jsonObj.getString("examinationPaper_id")!= null && (!jsonObj.getString ("examinationPaper_id").equals("")))
            curForm.setExaminationPaper_id(jsonObj.getLong("examinationPaper_id"));
        //剩余时间                                                 
        if(jsonObj.getString("leavTime") != null && (!jsonObj.getString("leavTime").equals("")))
            curForm.setLeavTime(jsonObj.getInt("leavTime"));
        //单位主键                                                 
        if(jsonObj.getString("organization_id")!= null && (!jsonObj.getString ("organization_id").equals("")))
            curForm.setOrganization_id(jsonObj.getLong("organization_id"));
        //考试主键                                                 
        if(jsonObj.getString("id")!= null && (!jsonObj.getString("id").equals("")))
            curForm.setId(jsonObj.getLong("id"));
        //考场主键                                                 
        if(jsonObj.getString("examroom_id")!= null && (!jsonObj.getString ("examroom_id").equals("")))
            curForm.setExamroom_id(jsonObj.getLong("examroom_id"));
        //用户主键                                                 
        if(jsonObj.getString("user_id")!= null && (!jsonObj.getString("user_id").equals("")))
            curForm.setUser_id(jsonObj.getLong("user_id"));
        //专业代码                                                 
        if(jsonObj.getString("specialtyCode")!= null && (!jsonObj.getString ("specialtyCode").equals("")))
            curForm.setSpecialtyCode(jsonObj.getLong("specialtyCode"));
        //报考岗位                                                 
        if(jsonObj.getString("postionCode")!= null && (!jsonObj.getString ("postionCode").equals("")))
            curForm.setPostionCode(jsonObj.getLong("postionCode"));
        //报考等级                                                 
        if(jsonObj.getString("gradeCode")!= null && (!jsonObj.getString ("gradeCode").equals("")))
            curForm.setGradeCode(jsonObj.getLong("gradeCode"));
        //考试开始时间                                             
        curForm.setExamStartTime(jsonObj.getString("examStartTime"));
        //考试结束时间                                             
        curForm.setExamEndTime(jsonObj.getString("examEndTime"));  
              ...
    }

优雅的赋值:

注:这里的下划线可以转换一下驼峰这里我要总结几篇文章

@JSONType(naming= PropertyNamingStrategy.SnakeCase)

    public class ExammingFormVo extends ExammingForm{
        private String examinationPaperId; //试卷主键              
        private String leavTime; //剩余时间                        
        private String organizationId; //单位主键                  
        private String id; //考试主键                              
        private String examRoomId; //考场主键                      
        private String userId; //用户主键                          
        private String specialtyCode; //专业代码                   
        private String postionCode; //报考岗位                     
        private String gradeCode; //报考等级                       
        private String examStartTime; //考试开始时间               
        private String examEndTime; //考试结束时间                 
              ...
    }
    public void setExammingForm(ExammingForm form,String parameters)throws BaseException {
        try {
            JSONObject json = new JSONObject(parameters);
            ExammingFormVo vo = JSONObject.parseObject(json,ExammingFormVo.class);
            form = vo;
        }catch (Exception e){
            e.printStackTrace();
        }
    }

更好地重构项目

请查看以下代码发现问题

  public void save(Student stu){
                String sql = "INSERT INTO t_student(name,age) VALUES(?,?)";
        Connection conn = null;
        Statement st = null;
        try{
            //1. 加载注册驱动                                          
            Class.forName("com.mysql.jdbc.Driver");
            //2. 获取数据库连接                                        
            conn=DriverManager.getConnection("jdbc:mysql:///jdbc_demo","root","root");
            //3. 创建语句对象                                          
            PreparedStatement ps=conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            //4. 执行SQL语句                                           
            ps.executeUpdate();
            //5. 释放资源                                              
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if(st != null)
                    st.close();
            }catch(SQLException e){
                e.printStackTrace();
            }finally{
                try{
                    if(conn != null)
                        conn.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }
    //删除学生信息                                             
    public void delete(Long id){
        String sql = "DELETE FROM t_student WHERE id=?";
        Connection conn = null;
        Statement st = null;
        try{
            //1. 加载注册驱动                                          
            Class.forName("com.mysql.jdbc.Driver");
            //2. 获取数据库连接                                        
            conn=DriverManager.getConnection("jdbc:mysql:///jdbc_demo","root","root");
            //3. 创建语句对象                                          
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,id);
            //4. 执行SQL语句                                           
            ps.executeUpdate();
            //5. 释放资源                                              
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if(st != null)
                    st.close();
            }catch(SQLException e){
                e.printStackTrace();
            }finally{
                try{
                    if(conn != null)
                        conn.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }
    //修改学生信息                                             
    public void update(Student stu){
        String sql = "UPDATE t_student SET name=?,age=? WHERE id=?";
        Connection conn = null;
        Statement st = null;
        try{
            //1. 加载注册驱动                                          
            Class.forName("com.mysql.jdbc.Driver");
            //2. 获取数据库连接                                        
            conn=DriverManager.getConnection("jdbc:mysql:///jdbc_demo","root","root");
            //3. 创建语句对象                                          
            PreparedStatement ps = conn.prepareStatement(sql);
            ps.setObject(1,stu.getName());
            ps.setObject(2,stu.getAge());
            ps.setObject(3,stu.getId());
            //4. 执行SQL语句                                           
            ps.executeUpdate();
            //5. 释放资源                                              
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            try{
                if(st != null)
                    st.close();
            }catch(SQLException e){
                e.printStackTrace();
            }finally{
                try{
                    if(conn != null)
                        conn.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }

上述代码的功能没问题,但是代码重复得太多,因此可以进行抽取,把重复代码放到一个工具类JdbcUtil里。

工具类:

  public class JdbcUtil {
        private JdbcUtil() { }
        static {
            //1. 加载注册驱动                                          
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static Connection getConnection() {
            try {
                //2. 获取数据库连接                                        
                return DriverManager.getConnection("jdbc:mysql:///jdbc_demo", "root", "root");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        //释放资源                                                 
        public static void close(ResultSet rs, Statement st, Connection conn) {
            try {
                if (rs != null)
                    rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (st != null)
                        st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (conn != null)
                            conn.close();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

只需要在实现类中直接调用工具类JdbcUtil中的方法即可。

    //增加学生信息
    public void save(Student stu) {
        String sql = "INSERT INTO t_student(name,age) VALUES(?,?)";
        Connection conn = null;
        PreparedStatement ps=null;
        try {
            conn = JDBCUtil.getConnection();
            //3. 创建语句对象
            ps = conn.prepareStatement(sql);
            ps.setObject(1, stu.getName());
            ps.setObject(2, stu.getAge());
            //4. 执行SQL语句
            ps.executeUpdate();
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, conn);
        }
    }
    //删除学生信息
    public void delete(Long id) {
        String sql = "DELETE FROM t_student WHERE id=?";
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn=JDBCUtil.getConnection();
            //3. 创建语句对象
            ps = conn.prepareStatement(sql);
            ps.setObject(1, id);
            //4. 执行SQL语句
            ps.executeUpdate();
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, conn);
        }
    }
    //修改学生信息
    public void update(Student stu) {
        String sql = "UPDATE t_student SET name=?,age=? WHERE id=?";
        Connection conn = null;
        PreparedStatement ps = null;
        try {
            conn=JDBCUtil.getConnection();
            //3. 创建语句对象
            ps = conn.prepareStatement(sql);
            ps.setObject(1, stu.getName());
            ps.setObject(2, stu.getAge());
            ps.setObject(3, stu.getId());
            //4. 执行SQL语句
            ps.executeUpdate();
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(null, ps, conn);
        }
    }
    public Student get(Long id) {
        String sql = "SELECT * FROM t_student WHERE id=?";
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        PreparedStatement ps=null;
        try {
            conn = JDBCUtil.getConnection();
            //3. 创建语句对象
            ps = conn.prepareStatement(sql);
            ps.setObject(1, id);
            //4. 执行SQL语句
            rs = ps.executeQuery();
            if (rs.next()) {
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu = new Student(id, name, age);
                return stu;
            }
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(rs, ps, conn);
        }
        return null;
    }
    public List<Student> list() {
        List<Student> list = new ArrayList<>();
        String sql = "SELECT * FROM t_student ";
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        PreparedStatement ps=null;
        try {
            conn=JDBCUtil.getConnection();
            //3. 创建语句对象
            ps = conn.prepareStatement(sql);
            //4. 执行SQL语句
            rs = ps.executeQuery();
            while (rs.next()) {
                long id = rs.getLong("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu = new Student(id, name, age);
                list.add(stu);
            }
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(rs, ps, conn);
        }
        return list;
    }

虽然完成了重复代码的抽取,但数据库中的账号密码等直接显示在代码中,不利于后期账户密码改动的维护。可以建立一个db.propertise文件,用来存储这些信息。

      driverClassName=com.mysql.jdbc.Driver 
              url=jdbc:mysql:///jdbcdemo            
              username=root                         
              password=root                         

只需要在工具类JdbcUtil中获取里面的信息即可。

    static {
        //1. 加载注册驱动                                          
        try {
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = loader.getResourceAsStream("db.properties");
            p = new Properties();
            p.load(inputStream);
            Class.forName(p.getProperty("driverClassName"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() {
        try {
            //2. 获取数据库连接                                        
            return DriverManager.getConnection(p.getProperty("url"), p.getProperty("username"),
                    p.getProperty("password"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

代码抽取到这里,貌似已经完成,但在实现类中,依然存在部分重复代码,在DML操作中,除了SQL和设置值的不同,其他都相同,把相同的部分抽取出来,把不同的部分通过参数传递进来,无法直接放在工具类中。此时,可以创建一个模板类JdbcTemplate,创建一个DML和DQL的模板来对代码进行重构。

    //查询统一模板
    public static List<Student> query(String sql,Object...params){
        List<Student> list=new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps=null;
        ResultSet rs = null;
        try {
            conn=JDBCUtil.getConnection();
            ps=conn.prepareStatement(sql);
            //设置值
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1, params[i]);
            }
            rs = ps.executeQuery();
            while (rs.next()) {
                long id = rs.getLong("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu = new Student(id, name, age);
                list.add(stu);
            }
            //5. 释放资源
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtil.close(rs, ps, conn);
        }
        return list;
    }
    实现类直接调用方法即可。
    //增加学生信息
    public void save(Student stu) {
        String sql = "INSERT INTO t_student(name,age) VALUES(?,?)";
        Object[] params=new Object[]{stu.getName(),stu.getAge()};
        JdbcTemplate.update(sql, params);
    }
    //删除学生信息
    public void delete(Long id) {
        String sql = "DELETE FROM t_student WHERE id = ?";
        JdbcTemplate.update(sql, id);
    }
    //修改学生信息
    public void update(Student stu) {
        String sql = "UPDATE t_student SET name = ?,age = ? WHERE id = ?";
        Object[] params=new Object[]{stu.getName(),stu.getAge(),stu.getId()};
        JdbcTemplate.update(sql, params);
    }
    public Student get(Long id) {
        String sql = "SELECT * FROM t_student WHERE id=?";
        List<Student> list = JDBCTemplate.query(sql, id);
        return list.size()>0? list.get(0):null;
    }
    public List<Student> list() {
        String sql = "SELECT * FROM t_student ";
        return JDBCTemplate.query(sql);
    }

这样重复的代码基本就解决了,但有一个很严重的问题,就是这个程序DQL操作中只能处理Student类和t_student表的相关数据,无法处理其他类,比如Teacher类和t_teacher表。不同的表(不同的对象)应该有不同的列,不同列处理结果集的代码就应该不一样,处理结果集的操作只有DAO自己最清楚。也就是说,处理结果的方法根本就不应该放在模板方法中,应该由每个DAO自己来处理。因此,可以创建一个IRowMapper接口来处理结果集。

    public interface IRowMapper {
        //处理结果集                                   
        List rowMapper(ResultSet rs) throws Exception;
    }

DQL模板类中调用IRowMapper接口中的handle方法,提醒实现类自己去实现mapping方法。

public static List<Student> query(String sql,IRowMapper rsh, Object...params){
        List<Student> list = new ArrayList<>();
        Connection conn = null;
        PreparedStatement ps=null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            ps = conn.prepareStatement(sql);
            //设置值                                                   
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1, params[i]);
            }
            rs = ps.executeQuery();
            return rsh.mapping(rs);
            //5. 释放资源                                              
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(rs, ps, conn);
        }
        return list ;
    }

实现类自己去实现IRowMapper接口的mapping方法,想要处理什么类型的数据在里面定义即可。

    public Student get(Long id) {
        String sql = "SELECT * FROM t_student WHERE id = ?";
        List<Student> list = JdbcTemplate.query(sql,new StudentRowMapper(), id);
        return list.size()>0? list.get(0):null;
    }
    public List<Student> list() {
        String sql = "SELECT * FROM t_student ";
        return JdbcTemplate.query(sql,new StudentRowMapper());
    }
    class StudentRowMapper implements IRowMapper{
        public List mapping(ResultSet rs) throws Exception {
            List<Student> list=new ArrayList<>();
            while(rs.next()){
                long id = rs.getLong("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu=new Student(id, name, age);
                list.add(stu);
            }
            return list;
        }
    }

到这里为止,实现ORM的关键代码已经大功告成,但是DQL查询不单单要查询学生信息(List类型),还要查询学生数量,这时就要通过泛型来完成。

    public interface IRowMapper<T> {
        //处理结果集                                               
        T mapping(ResultSet rs) throws Exception;
    }
    public static <T> T query(String sql,IRowMapper<T> rsh, Object...params){
        Connection conn = null;
        PreparedStatement ps=null;
        ResultSet rs = null;
        try {
            conn = JdbcUtil.getConnection();
            ps = conn.prepareStatement(sql);
            //设置值                                                   
            for (int i = 0; i < params.length; i++) {
                ps.setObject(i+1, params[i]);
            }
            rs = ps.executeQuery();
            return rsh.mapping(rs);
            //5. 释放资源                                              
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(rs, ps, conn);
        }
        return null;
    }

StudentRowMapper类的代码如下。

    class StudentRowMapper implements IRowMapper<List<Student>>{
        public List<Student> mapping(ResultSet rs) throws Exception {
            List<Student> list=new ArrayList<>();
            while(rs.next()){
                long id = rs.getLong("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                Student stu=new Student(id, name, age);
                list.add(stu);
            }
            return list;
        }
    }

这样,不仅可以查询List,还可以查询学生数量。

public Long getCount(){
        String sql = "SELECT COUNT(*) total FROM t_student";
        Long totalCount = (Long) JdbcTemplate.query(sql,
                new IRowMapper<Long>() {
                    public Long mapping(ResultSet rs) throws Exception {
                        Long totalCount = null;
                        if(rs.next()){
                            totalCount = rs.getLong("total");
                        }
                        return totalCount;
                    }
                });
        return totalCount;
    }

这样,重构设计就已经完成,好的代码能让我们以后维护更方便,因此学会对代码的重构是非常重要的。

3 经典框架都在用设计模式解决问题

比如,Spring就是一个把设计模式用得淋漓尽致的经典框架。本书会结合JDK、Spring、MyBatis、Netty、Tomcat、Dubbo等经典框架的源码对设计模式展开分析,帮助大家更好、更深入地理解设计模式在框架源码中的落地。

经典框架都在用设计模式解决问题

Spring就是一个把设计模式用得淋漓尽致的经典框架,其实从类的命名就能看出来,我来一一列举:

设计模式名称 举例
工厂模式 BeanFactory
装饰器模式 BeanWrapper
代理模式 AopProxy
委派模式 DispatcherServlet
策略模式 HandlerMapping
适配器模式 HandlerAdapter
模板模式 JdbcTemplate
观察者模式 ContextLoaderListener

围绕 Spring 的 IOC、AOP、MVC、JDBC这样的思路展开,根据其设计类型来设计讲解顺序:

类型 名称 英文
创建型模式 工厂模式 Factory Pattern

单例模式
Singleton Pattern
原型模式 Prototype Pattern
结构型模式 适配器模式 Adapter Pattern
装饰器模式 Decorator Patter
代理模式 Proxy Pattern
行为性模式 策略模式 Strategy Pattern
模板模式 Template Pattern
委派模式 Delegate Pattern
观察者模式 Observer Pattern


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
9月前
|
设计模式 SQL Java
为什么一定要学习设计模式
先来看一个生活案例,当我们开心时,也许会寻求享乐。在学习设计模式之前,你可能会这样感叹:
37 0
|
10月前
|
设计模式 算法
设计模式学习
设计模式学习
|
11月前
|
设计模式
|
设计模式 自然语言处理 Java
重新学习设计模式一:什么是设计模式
一直以来,设计模式是一个令人头疼的课题,记得之前在A公司做智能客服项目时,刚开始只是一个小项目,不管什么设计模式,系统架构,全程直接上手敲业务代码,两三天时间就把所有的代码敲完上线使用,结果谁也没想到突然项目大起来了,十几个业务部门的业务一拥而上,开始招人,上手业务,结果。。。大家都是苦力干嘛,拼命加班,拼命填坑,十几个人的代码乱七八糟,大量重复业务,重复代码,单简单的一样表单业务查询就有三四不同的版本,新来的员工也在抱怨没学到任何技术,倒学会怎么跟业务吵架,那日子实在是不忍直视。。。
71 0
|
设计模式 存储 消息中间件
设计模式之美(二)——设计模式
《设计模式之美》是极客时间上的一个代码学习系列,在学习之后特在此做记录和总结。
设计模式之美(二)——设计模式
|
设计模式 存储 Java
设计模式日常学习(三)
创建者模式 二.工厂模式 在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦。 ● 简单工厂模式(不属于GOF的23种经典设计模式) ● 工厂方法模式 ● 抽象工厂模式 1.简单工厂模式 简单工厂不是一种设计模式,反而比较像是一种编程习惯。 1.1 结构 简单工厂包含如下角色: ●
72 0
|
存储 设计模式 算法
设计模式日常学习(七)
6.5 状态模式 6.5.1 概述 【例】通过按钮来控制一个电梯的状态,一个电梯有开门状态,关门状态,停止状态,运行状态。每一种状态改变,都有可能要根据其他状态来更新处理。例如,如果电梯门现在处于运行时状态,就不能进行开门操作,而如果电梯门是停止状态,就可以执行开门操作。 类图如下: public interface ILift { //电梯的4个状态 //开门状态 public final static int OPENING_STATE = 1; //关门状态 public final static int CLOSING_STATE = 2;
85 0
|
设计模式 算法 安全
设计模式日常学习(四)
三.原型模式 概述 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。 结构 原型模式包含如下角色: ● 抽象原型类:规定了具体原型对象必须实现的的 clone() 方法。 ● 具体原型类:实现抽象原型类的 clone() 方法,它是可被复制的对象。 ● 访问类:使用具体原型类中的 clone() 方法来复制新的对象。 实现 原型模式的克隆分为浅克隆和深克隆。 浅克隆:创建一个新对象,新对象的属性和原来对象完全相同,对于非基本类型属性,仍指向原有属性所指向的对象的内存地址。 深克隆:创建一个新对象,属性中引用的其他对象也会被克隆,不再指向原有对象地址。 Ja
53 0
|
设计模式 安全 Java
设计模式日常学习(二)
跟着黑马的视频学习设计模式总结记录 地址:BV1Np4y1z7BU 软件设计原则 在软件开发中,为了提高软件系统的可维护性和可复用性,增加软件的可扩展性和灵活性,程序员要尽量根据6条原则来开发程序,从而提高软件开发效率、节约软件开发成本和维护成本。 一.开闭原则 对扩展开放,对修改关闭。 在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。 想要达到这样的效果,我们需要使用接口和抽象类。 因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保持软件架构的稳定。而软件中易变的细节可以从抽象派生来的实现类来进行扩展,当软件需要发生变
76 0
|
设计模式 存储 安全
设计模式日常学习(五)
五.结构型模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: ● 代理模式 ● 适配器模式 ● 装饰者模式 ● 桥接模式 ● 外观模式 ● 组合模式 ● 享元模式 5.1.代理模式 5.1.1 概述 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。
96 0