设计模式基本概述

基本概述

    • 一.什么是设计模式
    • 二.设计模式的好处
    • 三.设计模式的基本原则
      • 1.开闭原则
      • 2.里氏替换原则
      • 3.依赖倒置原则
      • 4.单一职责原则
      • 5.接口隔离原则
      • 6.合成复用原则
      • 7.迪米特法则
    • 四.设计模式有哪些分类
      • 1.创建型模式
      • 2.结构型模式
      • 3.行为型模式

一.什么是设计模式

  • 在软件工程中,设计模式是对软件设计中普遍存在的各种问题所提出的一些通用解决方案,这个术语是由艾丽希·伽玛等人在1990年代从建筑设计领域引入到计算机科学来的。
  • 设计模式是人们在面对同类型的软件工程设计问题时所总结出的一些有用经验,把这些经验构成了一种思维模式,注意模式不是代码,而是某类问题的通用设计解决方案。
  • 我们知道软件工程方法学的三要素分别是:过程、工具和方法,而设计模式就好比是具体的方法和工具,它的主要目的是使软件工程的设计在维护性、扩展性、变化性、复杂度等方面得到一个很好的提升优化。

二.设计模式的好处

  • 能够提高代码的重用性
  • 能够提高代码的灵活性
  • 能够提高代码的可读性
  • 能够提高系统的扩展性
  • 能够提高系统的健壮性
  • 能够提高系统的稳定性
  • 能够提高软件的可维护性
  • 能够提高系统的开发效率

三.设计模式的基本原则

1.开闭原则

开闭原则就是说对扩展开放,对修改关闭,当软件的需求需要改变时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。它也是最基础、最重要的设计原则。

  • 代码示例

    违背开闭原则

    public class A{
        public static void main(String[] args){
            DrawShape d = new DrawShape();
            d.draw(new Triangle());
            d.draw(new Circle());
        }
    }
    
    class Shape{
        int shapeType;
    }
    
    class Triangle extends Shape{
        public Triangle(){
            super.shapeType = 1;
        }
    }
    
    class Circle extends Shape{
        public Triangle(){
            super.shapeType = 2;
        }
    }
    
    class DrawShape{
        public void draw(Shape shape){
            if(shape.shapeType == 1){
                drawTriangle();
            }else if(shape.shapeType == 2){
                drawCircle();
            }
        }
        
        private void drawTriangle(){
            System.out.println("画三角形");
        }
        
        private void drawCircle(){
            System.out.println("画圆形");
        }
    }
    

    遵循开闭原则

    public class A{
        public static void main(String[] args){
            DrawShape d = new DrawShape();
            d.draw(new Triangle());
            d.draw(new Circle());
        }
    }
    
    abstract class Shape{
        public abstract void draw(){
            System.out.println("画默认的图形");
        }
    }
    
    class Triangle extends Shape{
        public void draw(){
            System.out.println("画三角形");
        }
    }
    
    class Circle extends Shape{
        public void draw(){
            System.out.println("画圆形");
        }
    }
    
    class DrawShape{
        public void draw(Shape shape){
            shape.draw();
        }
    }
    
  • 作用优点

    • 能够使应用程序更易于维护和扩展

2.里氏替换原则

里氏替换原则就是说继承必须确保父类所拥有的性质在子类中仍然成立,即在基类出现的地方,其子类一定可以出现,子类可以扩展基类的功能,但是尽量不要重写基类的功能,不过可以通过聚合、组合、依赖等关系解决此问题。

  • 代码示例

    违背里氏替换

    public class A{
        public static void main(String[] args){
            B b = new B();
            System.out.println("5 + 6 =" + b.fun1());
            System.out.println("5 * 6 =" + b.fun2());
        }
    }
    
    class A{
        public int fun1(int a, int b){
            return a + b;
        }
    }
    
    class B extends A{
        public int fun1(int a, int b){
            return a - b;
        }
        
        public int fun2(int a, int b){
            return a * b;
        }
    }
    

    遵循里氏替换

    public class A{
        public static void main(String[] args){
            B b = new B();
            System.out.println("5 + 6 =" + b.fun3());
            System.out.println("5 * 6 =" + b.fun2());
        }
    }
    
    class Base(){
        
    }
    
    class A extends Base{
        public int fun1(int a, int b){
            return a + b;
        }
    }
    
    class B extends Base{
        private A a = new A();
        
        public int fun1(int a, int b){
            return a - b;
        }
        
        public int fun2(int a, int b){
            return a * b;
        }
        
        public int fun3(int a, int b){
            return a.fun1(a, b);
        }
    }
    
  • 作用优点

    • 可以规范我们在正确的地方使用继承,而不至于造成继承的使用泛滥

3.依赖倒置原则

  • 依赖倒置原则是实现开闭原则的基础,就是说当我们在编写面向对象的应用程序时,我们需要面向接口或抽象类编程, 而不具体的依赖某个实现类,高层模块不应该依赖底层模块,抽象不应该依赖于细节。

    • 代码示例

      违背依赖倒置

      public class A{
          public static void main(String[] args){
              Person p = new Person();
              p.receiveMessage(new Email());
              p.receiveMessage(new Phone());
          }
      }
      
      class Email{
          public String getInfo(){
              return "邮件信息";
          }
      }
      
      class Phone{
          public String getInfo(){
              return "手机短信";
          }
      }
      
      class Person{
          public void receiveMessage(Email email){
              System.out.println(email.getInfo());
          }
          
          public void receiveMessage(Phone phone){
              System.out.println(phone.getInfo());
          }
      }
      

      遵循依赖倒置

      public class A{
          public static void main(String[] args){
              Person p = new Person();
              p.receiveMessage(new Email());
              p.receiveMessage(new Phone());
          }
      }
      
      interface Message{
          String getInfo();
      }
      
      class Email implements Message{
          public String getInfo(){
              return "邮件信息";
          }
      }
      
      class Phone implements Message{
          public String getInfo(){
              return "手机短信";
          }
      }
      
      class Person{
          public void receiveMessage(Message message){
              System.out.println(message.getInfo());
          }
      }
      
    • 作用优点

      • 提高了系统的稳定性
      • 提高了系统的可维护性
      • 提高了系统的可扩展性
    • 依赖关系传递方式

      • 通过接口传递

        interface Message{
            void getInfo(Mechain mechain);
        }
        
        interface Mechain{
            void do();
        }
        
        class Person implements Message{
            public void getInfo(Mechain mechain){
                System.out.println(mechain.do());
            }
        }
        
      • 通过构造器传递

        interface Message{
            void getInfo();
        }
        
        interface Mechain{
            void do();
        }
        
        class Person implements Message{
            private Mechain mechain;
            
            public Person(Mechain mechain){
                this.mechain = mechain;
            }
            
            public void getInfo(){
                System.out.println(this.mechain.do());
            }
        }
        
      • 通过setter器传递

        interface Message{
            void getInfo();
        }
        
        interface Mechain{
            void do();
        }
        
        class Person implements Message{
            private Mechain mechain;
            
            public void getInfo(){
                System.out.println(this.mechain.do());
            }
            
            public setMechain(Mechain mechain){
                this.mechain = mechain;
            }
        }
        

4.单一职责原则

单一职责原则就是说一个类应该有且仅有一个能够引起它变化的原因,也就是只负责一项职责,否则此类应该进行拆分。为什么一个类不允许承担多项职责,因为如果其中一个职责进行了修改,那么其它职责可能也会跟着修改,也就有可能导致其它职责的执行错误。

  • 代码示例

    违背单一职责

    public class A{
        public static void main(String[] args){
            Animal a1 = new Animal();
            a1.run("斑马");
            a1.run("鲸鱼");
            a1.run("老鹰");
        }
    }
    
    class Animal{
        public void run(String name){
            System.out.println(name + "在地上跑");
        }
    }
    

    遵循单一职责

    public class A{
        public static void main(String[] args){
            RoadAnimal a1 = new RoadAnimal();
            a1.run("斑马");
    
            AirAnimal a2 = new AirAnimal();
            a2.run("老鹰");
    
            WaterAnimal a3 = new WaterAnimal();
            a3.run("鲸鱼");
        }
    }
    
    class RoadAnimal{
        public void run(String name){
            System.out.println(name + "在地上跑");
        }
    }
    
    class AirAnimal{
        public void run(String name){
            System.out.println(name + "在天空飞");
        }
    }
    
    class WaterAnimal{
        public void run(String name){
            System.out.println(name + "在水里游");
        }
    }
    
  • 作用优点

    • 降低了代码的复杂度
    • 降低代码变更的风险
    • 提高了代码的可读性
    • 增强了系统的高内聚低耦合

5.接口隔离原则

接口隔离原则就是说当一个接口的功能和职责太多时,我们需要将这个大接口分割成若干小接口,每一个小接口只服务于其对应客户端的相关功能,不应该让客户端去依赖那些不需要使用的功能。

  • 代码示例

    违背接口隔离

    请添加图片描述

    public class Example{
        public static void main(String[] args){
            A a = new A(); // A依赖于B,但只使用了方法1、2、3,方法4和5造成浪费
            a.execute1(new B());
            a.execute2(new B());
            a.execute3(new B());
    		
            C c = new C(); // C依赖于D,但只使用了方法1、4、5,方法2和3造成浪费
            c.exceute1(new D());
            c.exceute4(new D());
            c.exceute5(new D());
        }
    }
    
    interface Interface1{
        void operation1();
        void operation2();
        void operation3();
        void operation4();
        void operation5();
    } 
    
    class B implements Interface1{
        public void operation1(){}
        public void operation2(){}
        public void operation3(){}
        public void operation4(){}
        public void operation5(){}
    }
    
    class D implements Interface1{
        public void operation1(){}
        public void operation2(){}
        public void operation3(){}
        public void operation4(){}
        public void operation5(){}
    }
    
    class A{
        public void execute1(Interface1 i1){ i1.operation1(); }
        public void execute2(Interface1 i1){ i1.operation2(); }
        public void execute3(Interface1 i1){ i1.operation3(); }
    }
    
    class C{
        public void execute1(Interface1 i1){ i1.operation1(); }
        public void execute4(Interface1 i1){ i1.operation4(); }
        public void execute5(Interface1 i1){ i1.operation5(); }
    }
    

    遵循接口隔离

    请添加图片描述

    public class Example{
        public static void main(String[] args){
            A a = new A();
            a.execute1(new B());
            a.execute2(new B());
            a.execute3(new B());
    		
            C c = new C();
            c.exceute1(new D());
            c.exceute4(new D());
            c.exceute5(new D());
        }
    }
    
    interface Interface1{
        void operation1();
    } 
    
    interface Interface2{
        void operation2();
        void operation3();
    } 
    
    interface Interface3{
        void operation4();
        void operation5();
    } 
    
    class B implements Interface1,Interface2{
        public void operation1(){}
        public void operation2(){}
        public void operation3(){}
    }
    
    class D implements Interface1,Interface3{
        public void operation1(){}
        public void operation4(){}
        public void operation5(){}
    }
    
    class A{
        public void execute1(Interface1 i1){ i1.operation1(); }
        public void execute2(Interface2 i2){ i2.operation2(); }
        public void execute3(Interface2 i2){ i2.operation3(); }
    }
    
    class C{
        public void execute1(Interface1 i1){ i1.operation1(); }
        public void execute4(Interface3 i3){ i3.operation4(); }
        public void execute5(Interface3 i3){ i3.operation5(); }
    }
    
  • 作用优点

    • 避免一个接口中包含很多不同的职责,让每个接口的职责比较分明
    • 增强了系统的高内聚低耦合

6.合成复用原则

合成复用原则就是说当我们需要复用一些系统的代码的时候,应该优先考虑组合或聚合的方式实现,其次再考虑使用继承的方式实现。 因为如果一个父类中的功能太多,而我们只想复用其中一小部分功能,那么继承就造成了不必要的麻烦。

  • 代码示例

    违背合成复用

    public class A{
        public static void main(String[] args){
            Bird bird = new Bird();
            bird.talk();
            bird.eat();
            bird.fly();
        }
    }
    
    class Action{
        public void eat(){
            System.out.println("吃饭");
        }
        
        public void fly(){
            System.out.println("天上飞");
        }
        
        public void swim(){
            System.out.println("水里游");
        }
        
        public void run(){
            System.out.println("地上跑");
        }
    }
    
    class Bird extends Action{
        public void talk(){
            System.out.println("叫");
        }
        
        public void eat(){
            super.eat();
        }
        
        public void fly(){
            super.fly();
        }
    }
    

    遵循合成复用

    public class A{
        public static void main(String[] args){
            Bird bird = new Bird();
            bird.talk();
            bird.eat();
            bird.fly();
        }
    }
    
    class Action{
        public void eat(){
            System.out.println("吃饭");
        }
        
        public void fly(){
            System.out.println("天上飞");
        }
        
        public void swim(){
            System.out.println("水里游");
        }
        
        public void run(){
            System.out.println("地上跑");
        }
    }
    
    class Bird{
        private Action action = new Action();
        
        public void talk(){
            System.out.println("叫");
        }
        
        public void eat(){
            action.eat();
        }
        
        public void fly(){
            action.fly();
        }
    }
    
  • 作用优点

    • 能够增强系统的维护性
    • 能够提高代码的可读性

7.迪米特法则

迪米特法则又称 “最少知道原则” , 也就是说 “只与朋友交谈,不与陌生人交谈”, 一个类对自己依赖的类知道的越少越好,尽量将实现逻辑封装在类的内部,对外提供public方法而不泄露内部信息。这句话的含义是如果两个类之间无需直接通信,那么就不应当发生直接的相互调用,而是通过提供另一种方法进行转发通信。如果一个类包含有其它类对象的依赖,那么此对象以成员变量、方法参数、方法返回值的形式出现就是朋友,此对象以局部变量的形式出现就是陌生人。

  • 代码示例

    违背迪米特法则

    public class A{
        public static void main(String[] args){
            School school = new School();
            school.printAllName(new TeacherManager(), new StudentManager());
        }
    }
    
    class Teacher{}
    
    class Student{}
    
    class TeacherManager{
        public List<Teacher> getTeachers(){
            return new ArrayList<Teacher>();
        }
    }
    
    class StudentManager{
        public List<Student> getStudents(){
            return new ArrayList<Student>{};
        }
    }
    
    class School{
        public void printAllName(TeacherManager tm, StudentManager sm){
            List<Teacher> teachers = tm.getTeachers();
            teachers.foreach(System.out::println);
            
            List<Student> students = sm.getStudents();
            students.foreach(System.out::println);
        }
    }
    

    遵循迪米特法则

    public class A{
        public static void main(String[] args){
            School school = new School();
            school.printAllName(new TeacherManager(), new StudentManager());
        }
    }
    
    class Teacher{}
    
    class Student{}
    
    class TeacherManager{
        private List<Teacher> getTeachers(){
            return new ArrayList<Teacher>();
        }
        
        public void printTeachers(){
            List<Teacher> teachers = this.getTeachers();
            teachers.foreach(System.out::println);
        }
    }
    
    class StudentManager{
        private List<Student> getStudents(){
            return new ArrayList<Student>{};
        }
        
        public void printStudents(){
            List<Student> students = this.getStudents();
            students.foreach(System.out::println);
        }
    }
    
    class School{
        public void printAllName(TeacherManager tm, StudentManager sm){
            tm.printTeachers();
    		sm.printStudents();
        }
    }
    
  • 作用优点

    • 降低系统的耦合性
    • 减少系统之间的关联程度

四.设计模式有哪些分类

1.创建型模式

创建型模式对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用进行一个分离。为了使软件的结构更加清晰,外界对于这些对象只需要知道它们共同的接口,而不需要清楚其中具体的实现细节,这也使得整个系统的设计更加符合单一职责原则。

名称核心作用
单例模式(Singleton)保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
工厂模式(Factory)在创建一个对象时不向用户展示内部细节,而是提供一个创建对象的通用接口
抽象工厂模式(Abstract Factory)提供一个统一的接口,用于创建相关的对象家族
建造者模式(Builder)封装一个对象的建造过程,并按照这个过程创建相应的对象
原型模式(Prototype)使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象

2.结构型模式

结构型模式描述如何将类或者对象结合在一起形成更大的结构,就像搭积木,可以通过简单积木的组合形成复杂的、功能更为强大的结构。

其中又可以分为类结构型模式和对象结构型模式:

  • 类结构型模式主要关心的是类的组合,由多个类可以组合成一个更大的系统,在类结构型模式中一般只存在继承关系和实现关系。

  • 对象结构型模式主要关心的是类与对象的组合,通过关联关系使得在一 个类中定义另一个类的实例对象,然后通过该对象调用其方法。

名称核心作用
适配器模式(Adapter)把一个类接口转换成另一个类所需要的接口
桥接模式(Bridge)将抽象与实现分离开来,使它们可以独立变化
装饰器模式(Director)提供一种内部方法,使得能够为对象动态的添加功能
组合模式(Composite)将对象组合成树形结构来表示“整体/部分”层次关系
外观模式(Facade)提供一个统一的接口,用来访问内部的其它接口,从而让子系统更容易使用
享元模式(Flyweight)利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的
代理模式(Proxy)控制对某一类对象的直接访问,采用代理的手段间接访问

3.行为型模式

行为型模式是对在不同的对象之间划分责任的抽象化方法,不仅仅关注类和对象的结构,而且重点关注类和对象之间的相互作用。

其中又可以分为类行为型模式和对象行为型模式:

  • 类的行为型模式使用继承关系在几个类之间分配行为,类行为型模式主要通过多态等方式来分配父类与子类的职责。

  • 对象的行为型模式则使用对象的聚合关联关系来分配行为,对象行为型模式主要是通过对象关联等方式来分配两个或多个类的职责。

名称核心作用
命令模式(Command)将命令封装成对象,可以用来参数化其它对象
迭代器模式(Iterator)提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部细节
观察者模式(Observer)当一个对象状态改变时,它的所有依赖对象都会收到通知并且自动更新状态
中介者模式(Mediator)集中相关对象之间复杂的沟通和控制方式
备忘录模式(Memento)获得对象的内部状态,从而在需要时可以将对象恢复到最初状态
模板方法模式(Template)通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构
解释器模式(Interpreter)为语言创建解释器,通常由语言的语法和语法分析来定义
状态模式(State)允许对象在内部状态发生改变时改变它自身的行为
责任链模式(Responsibility)使多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系
策略模式(Strategy)定义一系列实现方法,在需要的时候调用相应的实现方案
访问者模式(Visitor)为一个对象结构增加新的能力

热门文章

暂无图片
编程学习 ·

Java输出数组的内容

Java输出数组的内容_一万个小时-CSDN博客_java打印数组内容1. 输出内容最常见的方式// List<String>类型的列表List<String> list new ArrayList<String>();list.add("First");list.add("Second");list.add("Third");list.ad…
暂无图片
编程学习 ·

母螳螂的“魅惑之术”

在它们对大蝗虫发起进攻的时候&#xff0c;我认认真真地观察了一次&#xff0c;因为它们突然像触电一样浑身痉挛起来&#xff0c;警觉地面对限前这个大家伙&#xff0c;然后放下自己优雅的身段和祈祷的双手&#xff0c;摆出了一个可怕的姿势。我被眼前的一幕吓到了&#xff0c;…
暂无图片
编程学习 ·

疯狂填词 mad_libs 第9章9.9.2

#win7 python3.7.0 import os,reos.chdir(d:\documents\program_language) file1open(.\疯狂填词_d9z9d2_r.txt) file2open(.\疯狂填词_d9z9d2_w.txt,w) words[ADJECTIVE,NOUN,VERB,NOUN] str1file1.read()#方法1 for word in words :word_replaceinput(fEnter a {word} :)str1…
暂无图片
编程学习 ·

HBASE 高可用

为了保证HBASE是高可用的,所依赖的HDFS和zookeeper也要是高可用的. 通过参数hbase.rootdir指定了连接到Hadoop的地址,mycluster表示为Hadoop的集群. HBASE本身的高可用很简单,只要在一个健康的集群其他节点通过命令 hbase-daemon.sh start master启动一个Hmaster进程,这个Hmast…
暂无图片
编程学习 ·

js事件操作语法

一、事件的绑定语法 语法形式1 事件监听 标签对象.addEventListener(click,function(){}); 语法形式2 on语法绑定 标签对象.onclick function(){} on语法是通过 等于赋值绑定的事件处理函数 , 等于赋值本质上执行的是覆盖赋值,后赋值的数据会覆盖之前存储的数据,也就是on…
暂无图片
编程学习 ·

Photoshop插件--晕影动态--选区--脚本开发--PS插件

文章目录1.插件界面2.关键代码2.1 选区2.2 动态晕影3.作者寄语PS是一款栅格图像编辑软件&#xff0c;具有许多强大的功能&#xff0c;本文演示如何通过脚本实现晕影动态和选区相关功能&#xff0c;展示从互联网收集而来的一个小插件&#xff0c;供大家学习交流&#xff0c;请勿…
暂无图片
编程学习 ·

vs LNK1104 无法打开文件“xxx.obj”

写在前面&#xff1a; 向大家推荐两本新书&#xff0c;《深度学习计算机视觉实战》和《学习OpenCV4&#xff1a;基于Python的算法实战》。 《深度学习计算机视觉实战》讲了计算机视觉理论基础&#xff0c;讲了案例项目&#xff0c;讲了模型部署&#xff0c;这些项目学会之后可以…
暂无图片
编程学习 ·

工业元宇宙的定义与实施路线图

工业元宇宙的定义与实施路线图 李正海 1 工业元宇宙 给大家做一个关于工业元宇宙的定义。对于工业&#xff0c;从设计的角度来讲&#xff0c;现在的设计人员已经做到了普遍的三维设计&#xff0c;但是进入元宇宙时代&#xff0c;就不仅仅只是三维设计了&#xff0c;我们的目…
暂无图片
编程学习 ·

【leectode 2022.1.15】完成一半题目

有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 2*N 道题目&#xff0c;整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题&#xff0c;请返回被选的 N 道题目至少包含多少种知识点类型。 示例 1&#xff1a…
暂无图片
编程学习 ·

js 面试题总结

一、js原型与原型链 1. prototype 每个函数都有一个prototype属性&#xff0c;被称为显示原型 2._ _proto_ _ 每个实例对象都会有_ _proto_ _属性,其被称为隐式原型 每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype 3. constructor 每个prot…
暂无图片
编程学习 ·

java练习代码

打印自定义行数的空心菱形练习代码如下 import java.util.Scanner; public class daYinLengXing{public static void main(String[] args) {System.out.println("请输入行数");Scanner myScanner new Scanner(System.in);int g myScanner.nextInt();int num g%2;//…
暂无图片
编程学习 ·

RocketMQ-什么是死信队列?怎么解决

目录 什么是死信队列 死信队列的特征 死信消息的处理 什么是死信队列 当一条消息初次消费失败&#xff0c;消息队列会自动进行消费重试&#xff1b;达到最大重试次数后&#xff0c;若消费依然失败&#xff0c;则表明消费者在正常情况下无法正确地消费该消息&#xff0c;此时…
暂无图片
编程学习 ·

项目 cg day04

第4章 lua、Canal实现广告缓存 学习目标 Lua介绍 Lua语法 输出、变量定义、数据类型、流程控制(if..)、循环操作、函数、表(数组)、模块OpenResty介绍(理解配置) 封装了Nginx&#xff0c;并且提供了Lua扩展&#xff0c;大大提升了Nginx对并发处理的能&#xff0c;10K-1000K Lu…
暂无图片
编程学习 ·

输出三角形

#include <stdio.h> int main() { int i,j; for(i0;i<5;i) { for(j0;j<i;j) { printf("*"); } printf("\n"); } }
暂无图片
编程学习 ·

stm32的BOOTLOADER学习1

序言 最近计划学习stm32的BOOTLOADER学习,把学习过程记录下来 因为现在网上STM32C8T6还是比较贵的,根据我的需求flash空间小一些也可以,所以我决定使用stm32c6t6.这个芯片的空间是32kb的。 #熟悉芯片内部的空间地址 1、flash ROM&#xff1a; 大小32KB&#xff0c;范围&#xf…
暂无图片
编程学习 ·

通过awk和shell来限制IP多次访问之学不会你打死我

学不会你打死我 今天我们用shell脚本&#xff0c;awk工具来分析日志来判断是否存在扫描器来进行破解网站密码——限制访问次数过多的IP地址&#xff0c;通过Iptables来进行限制。代码在末尾 首先我们要先查看日志的格式&#xff0c;分析出我们需要筛选的内容&#xff0c;日志…
暂无图片
编程学习 ·

Python - 如何像程序员一样思考

在为计算机编写程序之前&#xff0c;您必须学会如何像程序员一样思考。学习像程序员一样思考对任何学生都很有价值。以下步骤可帮助任何人学习编码并了解计算机科学的价值——即使他们不打算成为计算机科学家。 顾名思义&#xff0c;Python经常被想要学习编程的人用作第一语言…
暂无图片
编程学习 ·

蓝桥杯python-数字三角形

问题描述 虽然我前后用了三种做法&#xff0c;但是我发现只有“优化思路_1”可以通过蓝桥杯官网中的测评&#xff0c;但是如果用c/c的话&#xff0c;每个都通得过&#xff0c;足以可见python的效率之低&#xff08;但耐不住人家好用啊&#xff08;哭笑&#xff09;&#xff09…