设计模式整理(个人笔记)

设计模式案例源码

github地址: 点击这里

原型模式

原型模式类图
在这里插入图片描述
Prototype:原型类,声名一个克隆自己的接口。
ConcretePrototype: 具体原型类,实现一个克隆自己的操作。
Client:让一个原型对象克隆自己,从而创建一个新的对象(属性一样)。
应用在spring的bean中。

建造者模式

在这里插入图片描述
以房子案例,分为以下几个部分
建造者模式分为,产品、抽象建造者、实际建造者(实现)、指挥者。
抽象工厂与建造者模式区别
在这里插入图片描述

适配器模式

类适配器
举例为手机需要充电器进行充电。
电源220 充电器(适配器将电压调为5V) 手机(要有充电功能)
在这里插入图片描述
对象适配器
在这里插入图片描述
接口适配器
在这里插入图片描述
AbsAdapter 空实现接口,然后A调用后,可以用匿名内部类进行覆盖空实现方法。从而调用某个类。
注:
Springmvc中在请求中就是用的适配器
实现请求类图为
在这里插入图片描述
通过请求来找到 Controller 然后HandlerAdapter 找到对应的适配器,通过对应的适配器,在执行相应的Controller方法。
在这里插入图片描述

桥接模式

最早需求为对手机进行分类整理。但是这种方式,会使得改什么都要相互关联
在这里插入图片描述
桥接模式
在这里插入图片描述
品牌为接口,实现类为不同品牌(没给我品牌有对应的功能)
定义手机 吧品牌属性接过,通过品牌 掉方法。
定义不同样式,继承手机,通过父类调用接口方法。
桥接模式思路为:把抽象的类(通过调用被人的方法)与实现(实际干活的)的分开
应用在JDBC连接为桥接模式
在这里插入图片描述

装饰者模式

案例为:点各类咖啡+奶/巧克力/豆浆,会有不同的价位。需要满足可扩展性等。
在这里插入图片描述
问题:选择的种类是在太多,如果按辛巴克的规模那将是无限多的。
引用到装饰者模式——动态的讲功能附加到对象上。
在这里插入图片描述

通过下图可以看出 被装饰者,是被包括在装饰者中。通过递归的方式,将被包裹的新对象又变为被装饰者。
在这里插入图片描述
个人思路:一个祖父类。被两个儿子继承,其中一个子类,需要接受另外一个子类的对象,
传递的是需要被装饰的类。多态的妙用。

JDK中的使用装饰者为IO流
在这里插入图片描述

组合模式

案例:为想展示出某个学校的目录层级,院,系。
如果不懂设计模式会想到继承关系,但是那是效率最低的。因此,可以用到部分整体模式,即——组合模式。
类图如下
在这里插入图片描述
注:聚合的是 由Organization类 分别聚合到College、University
这里如此画是因为方便体现
个人理解,因为学校、院、等功能与属性差不多、因此可以定义一个管理的抽象类,非叶子结点继承,并复写其方法,并且都聚合这个管理类。
叶子结点也要继承,但是不用复写方法。

外观模式

案例 :家庭电影,你需要,
在这里插入图片描述
非常的麻烦,你需要把所有的机器开关给点开。
传统解决方案。
在这里插入图片描述
可以看出是非常的不方便。
以下为外观模式设计图。
在这里插入图片描述
就是把各个子系统单例起来,然后在外观类聚合子系统,并将每个子系统的单例,分类(创建新的方法)调用。最后在客户端上直接调用外观类的方法。
该模式应用在MyBatis框架中的Configuration去创建MetaObject 。
该模式类图如下。
在这里插入图片描述

享元模式

案例:
在这里插入图片描述
享元模式类图
在这里插入图片描述
享元模式核心在于下面的代码

private HashMap<String,ConcreteWebSite> pool =new HashMap<>();
    public Website getweb(String Type){
        if(!pool.containsKey(Type)){
            pool.put(Type,new ConcreteWebSite(Type));
        }
        return (Website) pool.get(Type);
    }

可以看出享字的精髓在于 通过Hashmap 来控制,对不同的key会创造出新的value类对象,因此key相同时 ,是不会创造出新的对象的。

代理模式

静态代理
案例为,老师生病,代课老师来上课。类图如下
在这里插入图片描述
动态代理
在这里插入图片描述
类图如下
在这里插入图片描述
动态代理的核心为反射
核心代码如下

    public Object getProxyInstance(){
         //参数说明
        //1. ClassLoader loader :指定当前目标对象使用的类加载器,获取加载器的方法固定。
        //2.Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确定类型
        //3.InvocationHandler h:事件处理,执行目标对象的方法时,会触发事件处理器方法,会把当前执行的目标对象方法作为参数传入。
        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("JDK代理开始");
                //反射机制,调用目标对象
                Object returnval=method.invoke(target,args); //参数有则继续写
                System.out.println("JDK代理提交");
                return returnval;
            }
        });
    }

cglib代理
该代理在Spring 拦截机制中为主流使用。
注意事项。
在这里插入图片描述
类图如下
在这里插入图片描述
和动态代理差不多,1.只是用cglib进行(获取一个)get方法获取被代理类的class文件。
2.然后通过重写intecept进行对获取到的代理类进行具体操作。

模板方法

在这里插入图片描述
类图与解析如下
在这里插入图片描述
个人理解:就是在抽象类的方法中设置一个模板方法。(fina)不能被重写
模板方法(make)包括,(制作豆浆的步骤。)
然后通过通过创建子类的对象,返回值为父类的。调用make方法。
总结
在抽象方法中,有个方法负责调用,各个子类可以通过复写进行不同的操作(用多态)进行模板中的方法进行不同的书写。
钩子方法
可以定义一个布尔方法,通过子类复写,决定某个方法执行与否。
应用
Sping IOC 容器初始化时,用到了模板模式。

命令模式

以生活中的智能遥控器为例子 进行演示
在这里插入图片描述
遥控器代码如下

public class RemoteController {
    //各操作命令集合
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
    public RemoteController(){
        onCommands = new Command[5];
        offCommands = new Command[5];
        for(int i=0;i<5;i++){
            onCommands[i] = new NoCommand();
            offCommands[i] = new NoCommand();
        }
    }
    public void setCommands(int o,Command oncommand,Command offCommand)
    {
        onCommands[o]=oncommand;
        offCommands[o]=offCommand;
    }
    public void onButtonWasPushed(int o){
        onCommands[o].execete();
        //记录一下 用于撤销
        undoCommand=onCommands[o];
    }
    public void offButtonWasPushed(int o){
        offCommands[o].execete();
        //记录一下 用于撤销
        undoCommand=offCommands[o];
    }
    public void undoButtonWasPushed(int o){
        undoCommand.undo();
    }
}

总结:遥控器精髓就是定义一个接口(父)对象数组,通过编号进行存储对象(即子类/实现类对象),如果新增对象,我们只需要通过遥控器对象,调用set方法绑定对象即可。减小了代码耦合度。

访问者模式

案例应用
在这里插入图片描述
案例类图
在这里插入图片描述
总结:访问者模式为双分派,把人的分类,与行为的分类进行解耦。如果继续添加行为,也只需继续实现Action即可,无需改动。
与策略模式相同,都是符合开闭原则。

迭代器模式

案例为:展示学校的树形结构。
案例类图
在这里插入图片描述
总结:把数据添加与迭代进行分离。实现Iterator接口,把类变成迭代器类型的类。

观察者模式

案例为气象站为各个接入方提供数据,各个接入方为观察者。
案例类图:
在这里插入图片描述
总结:这是典型的一对多的问题,需要聚合多的一方的父类(实现类),这样大大的便于扩展。

中介者模式

在这里插入图片描述
案例类图
在这里插入图片描述
总结:就是单独写一个类,管理与类之间的关系。

备忘录模式

案例为游戏角色恢复。
在这里插入图片描述
总结就是:多创建一个Caretaker 用来备份当前的属性,(把当前对象传给备用类的引用)上图Memento 为备份属性类。

解析器模式

案例用解释器模式完成四则运算。
案例类图
在这里插入图片描述
这个模式的主要逻辑为,在创建不同的Calculator时,而创建不同的Expression子类对象。并通过HashMap 解析不同的Expression对象对应的值。然后通过堆栈: 堆栈介绍.进行管理被分解的式子元素
核心代码如下

package sun.Interpreter;

import java.util.HashMap;
import java.util.Stack;

public class Calculator
{
        //定义表达式
    private Expression expression;
    public Calculator(String exptre){
        Stack<Expression> stack=new Stack<>();
        //将表达式拆分成字符数组
        char[] charArray=exptre.toCharArray();
        Expression left=null;
        Expression right = null;
        //遍历char字符数组。
        //并对不同情况,做相应处理
        for(int i=0;i<charArray.length;i++)
        {
            switch (charArray[i]){
                case '+':
                    left = stack.pop(); //如果是+号 就先取出左表达式。
                    //因为符号附近为数字,因此创建Var类型的Expression
                    right = new VarExpression(String.valueOf(charArray[++i]));//然后取出右表达式。
                    stack.push(new AddExpression(left,right));
                    break;
                case '-':
                    left=stack.pop();
                    right=new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left,right));
                    break;
                default:
                    //如果是个Var 那么就继续往栈里放
                    stack.push(new VarExpression(String.valueOf(i)));
                    break;
            }
        }
        this.expression=stack.pop();
    }
    public int run(HashMap<String,Integer>var){
        return this.expression.interpreter(var);
    }
}

状态模式

状态模式案例:
在这里插入图片描述
案例类图:
在这里插入图片描述
总结:由于状态发生变化,会有不同的行为,因此把状态作为接口进行实现。活动类中要聚合所有的状态子类,所有的状态子类中也包含活动类。不同状态子类,通过调用Activity类设置该状态的行为。

策略模式

案例为鸭子,不同颜色的鸭子有不同的行为。
案例类图:
在这里插入图片描述
总结:策略模式为开闭原则的典型。我们可以把鸭子的每个行为,定为接口。因为每个行为比如飞翔,会有飞的高矮低等不同行为。只需要通过不同的接口,设置每个鸭子的不同行为即可。

职责链模式

案例需求:
在这里插入图片描述
案例类图:
在这里插入图片描述
总结:把请求与处理分开。最主要是 Approver 聚合自己后,可以通过设置子类实例调用,从而完成一串行为链。 设置行为链代码如下。
注意的是 我们需要设置结点数量,我们需要控制结点数量。

package ResponsibilityChain;

public class Client {


    public static void main(String[] args) {
        //创建请求
        PurchaseRequest purchaseRequest=new PurchaseRequest(1,50000,0155464);
        //创建角色
        DepartmentApprover departmentApprover=new DepartmentApprover("张主任");
        CollegeApprover collegeApprover=new CollegeApprover("李院士");
        ViceSchool viceSchool=new ViceSchool("陈副校长");
        SchoolMastApprover schoolMastApprover=new SchoolMastApprover("孙校长");
        //设置处理顺序(处理人应该构成一个环形)//这样有些低的请求校长也能处理
        departmentApprover.setApprover(collegeApprover);
        collegeApprover.setApprover(viceSchool);
        viceSchool.setApprover(schoolMastApprover);
        schoolMastApprover.setApprover(departmentApprover);

        //请求调用,从主任处理
        departmentApprover.processRequest(purchaseRequest);
    }
}

完结:

总结:纸上得来终觉潜,绝知此事要躬行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闯孙闯孙

觉得有用就赞一个呗

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值