设计模式

0x01 设计模式概述

  • 代表了代码的最佳实践
  • 设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结
  • 设计模式是为了复用代码,使代码更容易被理解,保证代码可靠性
  • 面向接口编程
  • 优先使用对象组合,而非继承关系

以下代码示例均采用 Java 语言(JDK 18)

0x02 七大基本原则

(1)开闭原则【Open Closed Principle,OCP】

  • 对扩展开放,对修改关闭

  • 使用抽象进行构建,使用实现扩展细节

  • 面向抽象编程

  • 提高软件系统的可复用性可维护性

  • 举例:人类的基础行为和身份带来的特有行为

    1. 新建 com.dp.principle.ocp 包,其中新建 Human 接口
      正常人类行为包括吃饭和睡觉

      package com.dp.principle.ocp;
      
      public interface Human {
          public void eat();
          public void sleep();
      }
      
    2. 新建 Student 类,实现 Human 接口并重写接口中的方法,添加特有方法 study()
      学生特有学习行为

      package com.dp.principle.ocp;
      
      public class Student implements Human {
          @Override
          public void eat() {
              System.out.println("Student is eating.");
          }
      
          @Override
          public void sleep() {
              System.out.println("Student is sleeping.");
          }
      
          public void study() {
              System.out.println("Student is studying.");
          }
      }
      
    3. 新建 Test 类测试

      package com.dp.principle.ocp;
      
      public class Test {
          public static void main(String[] args) {
              Student student = new Student();
              student.eat();
              student.sleep();
              student.study();
          }
      }
      

      至此已经简单地实现了接口的功能

    4. 为实现 OCP,新建 HighSchoolStudent 类,继承 Student 类

      package com.dp.principle.ocp;
      
      public class HighSchoolStudent extends Student {
          @Override
          public void eat() {
              System.out.println("High School Student is eating.");
          }
      
          @Override
          public void sleep() {
              System.out.println("High School Student is sleeping.");
          }
      
          @Override
          public void study() {
              System.out.println("High School Student is studying.");
          }
      
          public void doSomething() {
              System.out.println("A student in the high school.");
          }
      }
      

      之后在每个新的角色中创建 doSomething() 方法的特有方法,体现了 OCP 中对扩展开放

    5. 在 Test 类测试

      package com.dp.principle.ocp;
      
      public class Test {
          public static void main(String[] args) {
              HighSchoolStudent student = new HighSchoolStudent();
              student.eat();
              student.sleep();
              student.study();
              student.doSomething();
          }
      }
      

      至此,已完成 OCP 的实现:当需要添加或修改某个角色的特有方法时,只需修改相应的角色类即可,而无需修改 Human 接口和 Student 父类

(2)依赖倒转原则【Dependency Inversion Principle,DIP】

  • 依赖倒转原则是开闭原则的基础,针对接口进行编程

  • 依赖抽象,而不是具体的实现

  • 可以减少类之间的耦合性,提高系统稳定性和代码可读性、可维护性,降低修改程序所造成的风险

  • 举例:同类人在完成基础人类行为基础上,按照各自具体角色进行特定行为

    1. 新建 com.dp.principle.dip 包,其中新建 Human 接口

      package com.dp.principle.dip;
      
      public interface Human {
          public void eat();
          public void sleep();
      }
      
    2. 新建 Programmer 抽象类,实现 Human 接口,添加特有抽象方法 work()
      程序员特有工作方法

      package com.dp.principle.dip;
      
      public abstract class Programmer implements Human {
          @Override
          public void eat() {
              System.out.println("Programmer is eating.");
          }
      
          @Override
          public void sleep() {
              System.out.println("Programmer is sleeping.");
          }
      
          public abstract void work();
      }
      

      至此实现了针对接口编程以及依赖抽象

    3. 新建 JavaProgrammer 类,作为具体的程序员,继承 Programmer 类并重写 work() 方法

      package com.dp.principle.dip;
      
      public class JavaProgrammer extends Programmer {
          @Override
          public void work() {
              System.out.println("JavaProgrammer is working.");
          }
      }
      
    4. 新建 TestProgrammer 类

      package com.dp.principle.dip;
      
      public class TestProgrammer extends Programmer {
          @Override
          public void work() {
              System.out.println("TestProgrammer is working.");
          }
      }
      
    5. 新建 Test 类测试

      package com.dp.principle.dip;
      
      public class Test {
          public static void main(String[] args) {
              JavaProgrammer javaProgrammer = new JavaProgrammer();
              javaProgrammer.work();
              TestProgrammer testProgrammer = new TestProgrammer();
              testProgrammer.work();
          }
      }
      

      至此已实现减少类之间的耦合性

(3)单一职责原则【Single Responsibility Principle, SRP】

  • 一个类、接口、方法仅负责一项职责

  • 降低了程序的复杂度与程序修改带来的风险,提高程序可维护性

  • 举例:不同类型的行为进行分类设计

    1. 新建 com.dp.principle.srp 包,其中新建 Human 接口

      package com.dp.principle.dip;
      
      public interface Human {
          public void eat();
          public void sleep();
      }
      
    2. 新建 Programmer 抽象类,实现 Human 接口

      package com.dp.principle.srp;
      
      public abstract class Programmer implements Human {
          public abstract void work();
      }
      
    3. 新建 JavaProgrammer 类

      package com.dp.principle.srp;
      
      public class JavaProgrammer extends Programmer {
          @Override
          public void eat() {
              System.out.println("JavaProgrammer is eating.");
          }
      
          @Override
          public void sleep() {
              System.out.println("JavaProgrammer is sleeping.");
          }
      
          @Override
          public void work() {
              System.out.println("JavaProgrammer is working.");
          }
      }
      
    4. 新建 Test 类测试

      package com.dp.principle.srp;
      
      public class Test {
          public static void main(String[] args) {
              JavaProgrammer javaProgrammer = new JavaProgrammer();
              javaProgrammer.eat();
              javaProgrammer.sleep();
              javaProgrammer.work();
          }
      }
      
    5. 当在 JavaProgrammer 类中添加新的订外卖方法时,该类就出现了两个职责:工作、订外卖,此时违背了单一职责原则,需要另外新建一个类负责订外卖职责
      新建 Order 类,local() 方法表示“堂食”,take() 方法表示“外卖”

      package com.dp.principle.srp;
      
      public class Order {
          public void local() {
              System.out.println("堂食");
          }
          public void take() {
              System.out.println("外卖");
          }
      }
      
    6. 在 JavaProgrammer 类中引入 Order 类,并添加 setter 方法、修改 eat 方法

      package com.dp.principle.srp;
      
      public class JavaProgrammer extends Programmer {
          private Order order;
      
          public void setOrder(Order order) {
              this.order = order;
          }
      
          @Override
          public void eat() {
              order.take();
          }
      }
      
    7. 在 Test 类中测试

      package com.dp.principle.srp;
      
      public class Test {
          public static void main(String[] args) {
              JavaProgrammer javaProgrammer = new JavaProgrammer();
              
              Order order = new Order();
              javaProgrammer.setOrder(order);
              javaProgrammer.eat();
              
              javaProgrammer.sleep();
              javaProgrammer.work();
          }
      }
      

(4)接口隔离原则【Interface Segregation Principle,ISP】

  • 使用多个接口

  • 尽量细化接口,接口中的方法尽可能少

  • 符合低耦合的设计思想,提供了可扩展性和可维护性

  • 举例:将人类的基础行为分别设计

    1. 新建 com.dp.principle.isp 包,其中新建三个接口

      • Human

        package com.dp.principle.isp;
        
        public interface Human {
        }
        
      • EatAction

        package com.dp.principle.isp;
        
        public interface EatAction extends Human {
            public void eat();
        }
        
      • SleepAction

        package com.dp.principle.isp;
        
        public interface SleepAction extends Human {
            public void sleep();
        }
        
    2. 新建 Student 类实现上述接口

      package com.dp.principle.isp;
      
      public class Student implements EatAction, SleepAction {
          @Override
          public void eat() {
              System.out.println("Student is eating.");
          }
      
          @Override
          public void sleep() {
              System.out.println("Student is sleeping.");
          }
      }
      
    3. 新建 Test 类测试

      package com.dp.principle.isp;
      
      public class Test {
          public static void main(String[] args) {
              Student student = new Student();
              student.eat();
              student.sleep();
          }
      }
      

(5)迪米特原则【Law of Demeter,LOD】

  • 又称最少知识原则,一个对象应对其他对象保持最少的了解

  • 降低类与类之间的耦合关系

  • 强调只与“朋友”(成员变量、方法参数等)交流

  • 举例:老板给项目经理开会,由项目经理传达任务

    1. 新建 com.dp.principle.lod 包,其中新建 Human 接口

      package com.dp.principle.lod;
      
      public interface Human {
      }
      
    2. 新建 Programmer 抽象类实现 Human 接口

      package com.dp.principle.lod;
      
      public abstract class Programmer implements Human {
          public abstract void work();
      }
      
    3. 新建 JavaProgrammer 类和 PythonProgrammer 类继承 Programmer 类

      package com.dp.principle.lod;
      
      public class JavaProgrammer extends Programmer {
          @Override
          public void work() {
              System.out.println("JavaProgrammer is working.");
          }
      }
      
      package com.dp.principle.lod;
      
      public class PythonProgrammer extends Programmer {
          @Override
          public void work() {
              System.out.println("PythonProgrammer is working.");
          }
      }
      
    4. 新建 Manager 接口,继承 Human 接口

      package com.dp.principle.lod;
      
      public interface Manager extends Human {
      }
      
    5. 新建 Boss 类实现 Manager 接口,添加“开会”方法

      package com.dp.principle.lod;
      
      public class Boss implements Manager {
          public void meet() {
              System.out.println("Boss is meeting.");
          }
      }
      
    6. 新建 TeamLeader 类实现 Manager 接口,添加“分配工作”方法

      package com.dp.principle.lod;
      
      public class TeamLeader implements Manager {
          public void assign() {
              System.out.println("TeamLeader is assigning tasks.");
          }
      }
      
    7. 在 Boss 接口中,修改 meet() 方法,以成员变量的方式传递 TeamLeader 接口,从而实现 Boss 通过 TeamLeader 分配工作

      public void meet(TeamLeader teamLeader) {
          System.out.println("Boss is meeting.");
          teamLeader.assign();
      }
      
    8. 在 TeamLeader 接口中,实现工作的分配

      package com.dp.principle.lod;
      
      public class TeamLeader implements Manager {
          private Programmer programmer;
      
          public void setProgrammer(Programmer programmer) {
              this.programmer = programmer;
          }
      
          public void assign() {
              System.out.println("TeamLeader is assigning tasks.");
      
              if(programmer instanceof JavaProgrammer) {
                  ((JavaProgrammer)programmer).work();
              } else if(programmer instanceof PythonProgrammer) {
                  ((PythonProgrammer)programmer).work();
              }
          }
      }
      
    9. 新建 Test 类测试

      package com.dp.principle.lod;
      
      public class Test {
          public static void main(String[] args) {
              Boss boss = new Boss();
              TeamLeader teamLeader = new TeamLeader();
              JavaProgrammer javaProgrammer = new JavaProgrammer();
              PythonProgrammer pythonProgrammer = new PythonProgrammer();
      
              // 老板找项目经理开会
              boss.meet(teamLeader);
              // 项目经理找 Java 程序员
              teamLeader.setProgrammer(javaProgrammer);
              // 布置任务
              teamLeader.assign();
              // 项目经理找 Python 程序员
              teamLeader.setProgrammer(pythonProgrammer);
              // 布置任务
              teamLeader.assign();
          }
      }
      

(6)里氏替换原则【Liskov Substitution Principle,LSP】

  • 是继承复用的基石,是对开闭原则(OCP)的补充

  • 子类既可以增加自己特有的方法,也可以扩展父类的功能,但是不能改变父类原有的功能

  • 子类可以实现父类的抽象方法,但是不能覆盖父类原有的方法

  • 对子类的继承关系进行约束,此为对 OCP 的补充

  • 可以增加程序的健壮性

  • 举例:老师给学生留作业

    1. 新建 com.dp.principle.lsp 包,其中新建 Teacher 类

      package com.dp.principle.lsp;
      
      public class Teacher {
          public int fun1(int a, int b) {
              return a+b;
          }
      }
      
    2. 新建 Student 类,继承 Teacher 类,“不小心”重写了 fun1() 方法并添加特有方法 fun2()

      package com.dp.principle.lsp;
      
      public class Student extends Teacher {
          @Override
          public int fun1(int a, int b) {
              return a-b;
          }
          
          public int fun2(int a, int b) {
              return (a+b)+10;
          }
      }
      
    3. 新建 Test 类测试

      package com.dp.principle.lsp;
      
      public class Test {
          public static void main(String[] args) {
              Teacher teacher = new Teacher();
              System.out.println(teacher.fun1(1, 2));
      
              Student student = new Student();
              System.out.println(student.fun1(1, 2));
          }
      }
      

      此时已经违背了里氏替换原则

    4. 为防止子类不小心重写父类方法,在此新建 Human 类

      package com.dp.principle.lsp;
      
      public class Human {
      }
      
    5. 设置 Teacher 类和 Student 类都继承自 Human 类,之后将 Teacher 类注入到 Student 类中

      • Teacher:添加继承

        package com.dp.principle.lsp;
        
        public class Teacher extends Human {
            public int fun1(int a, int b) {
                return a+b;
            }
        }
        
      • Student:修改继承,修改 fun1(),注入 Teacher

        package com.dp.principle.lsp;
        
        public class Student extends Human {
            private Teacher teacher;
        
            public void setTeacher(Teacher teacher) {
                this.teacher = teacher;
            }
        
            public int fun1(int a, int b) {
                return teacher.fun1(a, b);
            }
        
            public int fun2(int a, int b) {
                return (a+b)+10;
            }
        }
        
    6. 修改 Test 类

      package com.dp.principle.lsp;
      
      public class Test {
          public static void main(String[] args) {
              Teacher teacher = new Teacher();
              System.out.println(teacher.fun1(1, 2));
      
              Student student = new Student();
              student.setTeacher(teacher);
              System.out.println(student.fun1(1, 2));
          }
      }
      

(7)合成复用原则【Composite/Aggregate Reuse Principle,CARP】

  • 尽量使用对象的合成或聚合的方式,而非使用继承达到软件复用的目的

  • 使系统更加灵活,降低类与类之间的耦合度

    • 一个类的变化对其他类造成的影响相对较小
  • 举例:老师通知学生家长开会

    1. 新建 com.dp.principle.carp 包,其中新建 Teacher 类

      package com.dp.principle.carp;
      
      public class Teacher {
          public void call() {
              System.out.println("Call Alex's parents.");
          }
      }
      
    2. 新建 Student 类

      package com.dp.principle.carp;
      
      public class Student {
          public void notifyMeeting() {
              System.out.println("Notify parent to attend parent meeting.");
          }
      }
      
    3. 新建 Parent 类

      package com.dp.principle.carp;
      
      public class Parent {
          public void meeting() {
              System.out.println("Attend.");
          }
      }
      
    4. 新建 Test 类测试

      package com.dp.principle.carp;
      
      public class Test {
          public static void main(String[] args) {
              Teacher teacher = new Teacher();
              teacher.call();
              Student student = new Student();
              student.notifyMeeting();
              Parent parent = new Parent();
              parent.meeting();
          }
      }
      

      此时并没有达到合成复用原则,仅是达到基础目的,仍存在多处不足

    5. 新建 Notify 接口

      package com.dp.principle.carp;
      
      public interface Notify {
      }
      
    6. 新建 WxNotify 类实现 Notify 接口
      通过微信通知家长

      package com.dp.principle.carp;
      
      public class WxNotify implements Notify {
          private Parent parent;
      
          public void setParent(Parent parent) {
              this.parent = parent;
          }
      
          public void wxNotify() {
              parent.meeting();
          }
      }
      
    7. 新建 PhoneNotify 类实现 Notify 接口
      通过电话通知家长

      package com.dp.principle.carp;
      
      public class PhoneNotify implements Notify {
          private Parent parent;
      
          public void setParent(Parent parent) {
              this.parent = parent;
          }
      
          public void phoneNotify() {
              parent.meeting();
          }
      }
      
    8. 修改 Teacher 类

      package com.dp.principle.carp;
      
      public class Teacher {
          private Notify notify;
      
          public void setNotify(Notify notify) {
              this.notify = notify;
          }
      
          public void call() {
              if(notify instanceof WxNotify) {
                  ((WxNotify)notify).wxNotify();
              } else if (notify instanceof PhoneNotify) {
                  ((PhoneNotify)notify).phoneNotify();
              }
          }
      }
      
    9. 修改 Test 类

      package com.dp.principle.carp;
      
      public class Test {
          public static void main(String[] args) {
              Teacher teacher = new Teacher();
              Parent parent = new Parent();
              WxNotify wxNotify = new WxNotify();
              PhoneNotify phoneNotify = new PhoneNotify();
              wxNotify.setParent(parent);
              phoneNotify.setParent(parent);
              teacher.setNotify(wxNotify);
              teacher.call();
              teacher.setNotify(phoneNotify);
              teacher.call();
          }
      }
      

0x03 创建型模式

  • 提供实例化的方法,为适合的状况提供相应的对象创建方法。
    • 隐藏了创建对象的过程,通过逻辑方法进行创建对象,而不是通过 new 关键字进行创建
  • 社会化的分工越来越细,自然在软件设计方面也是如此,因此对象的创建和对象的使用分开也就成为了必然趋势。
  • 因为对象的创建会消耗掉系统的很多资源,所以单独对对象的创建进行研究,从而能够高效地创建对象就是创建型模式要探讨的问题。

(0)简单工厂模式【Simple Factory】

简单工厂设计模式并不包含在 GOF 的 23 种设计模式中

  • 由一个工厂决定创建哪种产品类型的实例

  • 举例:

    1. 新建 com.pattern.other.simplefactory 包,其中新建 Course 类

      package com.pattern.other.simplefactory;
      
      public abstract class Course {
          public abstract void make();
      }
      
    2. 新建 JavaCourse 类和 PythonCourse类,继承 Course 类

      package com.pattern.other.simplefactory;
      
      public class JavaCourse extends Course {
          @Override
          public void make() {
              System.out.println("Make Java course.");
          }
      }
      
      package com.pattern.other.simplefactory;
      
      public class PythonCourse extends Course {
          @Override
          public void make() {
              System.out.println("Make Python course.");
          }
      }
      
    3. 新建 CourseFactory 类

      package com.pattern.other.simplefactory;
      
      public class CourseFactory {
          public Course getCourse(String course) {
              if("java".equalsIgnoreCase(course)) {
                  return new JavaCourse();
              } else if("python".equalsIgnoreCase(course)) {
                  return new PythonCourse();
              }
              return null;
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.other.simplefactory;
      
      public class Test {
          public static void main(String[] args) {
              CourseFactory factory = new CourseFactory();
              Course java = factory.getCourse("java");
              java.make();
              Course python = factory.getCourse("python");
              python.make();
          }
      }
      

(1)工厂方法模式【Factory Method】

  • 定义一个接口或一个抽象的工厂类,使其实现类来决定创建哪一个实例对象

  • 根据每个工厂不同的方法,来产生不同的所需要的对象

  • 举例:生产课程(同系列对象)

    1. 新建 com.pattern.creational.factorymethod 包,其中新建 Course 抽象类

      package com.pattern.creational.factorymethod;
      
      public abstract class Course {
          public abstract void make();
      }
      
    2. 新建 CourseFactory 抽象类

      package com.pattern.creational.factorymethod;
      
      public abstract class CourseFactory {
          public abstract Course getCourse();
      }
      
    3. 新建 JavaCourse 类和 PythonCourse 类,继承 Course 类

      package com.pattern.creational.factorymethod;
      
      public class JavaCourse extends Course {
          @Override
          public void make() {
              System.out.println("Make Java course.");
          }
      }
      
      package com.pattern.creational.factorymethod;
      
      public class PythonCourseFactory extends CourseFactory {
          @Override
          public Course getCourse() {
              return new PythonCourse();
          }
      }
      
    4. 新建 JavaCourseFactory 类和 PythonCourseFactory 类,继承 CourseFactory 类

      package com.pattern.creational.factorymethod;
      
      public class JavaCourseFactory extends CourseFactory {
          @Override
          public Course getCourse() {
              return new JavaCourse();
          }
      }
      
      package com.pattern.creational.factorymethod;
      
      public class PythonCourseFactory extends CourseFactory {
          @Override
          public Course getCourse() {
              return new PythonCourse();
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.creational.factorymethod;
      
      public class Test {
          public static void main(String[] args) {
              JavaCourseFactory javaCourseFactory = new JavaCourseFactory();
              Course javaCourse = javaCourseFactory.getCourse();
              javaCourse.make();
      
              PythonCourseFactory pythonCourseFactory = new PythonCourseFactory();
              Course pythonCourse = pythonCourseFactory.getCourse();
              pythonCourse.make();
          }
      }
      

(2)抽象工厂模式【Abstract Factory】

  • 抽象工厂模式提供了创建一系列相关或互相依赖对象的接口

  • 类似公司下的产品,产品不同系列

  • 举例:生产汽车

    1. 新建 com.pattern.creational.abstractfactory 包

    2. 新建 CarDoorFactory 抽象类,表示车门工厂类
      新建 CarDoor 类,继承 CarDoorFactory 类

      package com.pattern.creational.abstractfactory;
      
      public abstract class CarDoorFactory {
          public abstract void make();
      }
      
      package com.pattern.creational.abstractfactory;
      
      public class CarDoor extends CarDoorFactory {
          @Override
          public void make() {
              System.out.println("CarDoor is making.");
          }
      }
      
    3. 新建 BasePlateFactory 抽象类,表示底盘工厂类
      新建 CarDoor 类,继承 CarDoorFactory 类

      package com.pattern.creational.abstractfactory;
      
      public abstract class BasePlateFactory {
          public abstract void make();
      }
      
      package com.pattern.creational.abstractfactory;
      
      public class BasePlate extends BasePlateFactory {
          @Override
          public void make() {
              System.out.println("BasePlate is making.");
          }
      }
      
    4. 新建 CarFrameFactory 抽象类,表示车架工厂类
      新建 CarDoor 类,继承 CarDoorFactory 类

      package com.pattern.creational.abstractfactory;
      
      public abstract class CarFrameFactory {
          public abstract void make();
      }
      
      package com.pattern.creational.abstractfactory;
      
      public class CarFrame extends CarFrameFactory {
          @Override
          public void make() {
              System.out.println("CarFrame is making.");
          }
      }
      
    5. 新建 CarFactory 接口

      package com.pattern.creational.abstractfactory;
      
      public interface CarFactory {
          public CarDoor getCarDoor();
          public BasePlate getBasePlate();
          public CarFrame getFrame();
          public void make();
      }
      
    6. 新建 Car 类,实现 CarFactory 接口

      package com.pattern.creational.abstractfactory;
      
      public class Car implements CarFactory {
          private CarDoor carDoor = null;
          private BasePlate basePlate = null;
          private CarFrame carFrame = null;
          
          @Override
          public CarDoor getCarDoor() {
              carDoor = new CarDoor();
              return carDoor;
          }
      
          @Override
          public BasePlate getBasePlate() {
              basePlate = new BasePlate();
              return basePlate;
          }
      
          @Override
          public CarFrame getFrame() {
              carFrame = new CarFrame();
              return carFrame;
          }
      
          @Override
          public void make() {
              carDoor.make();
              basePlate.make();
              carFrame.make();
              System.out.println("The car is made!");
          }
      }
      
    7. 新建 Test 类测试

      package com.pattern.creational.abstractfactory;
      
      public class Test {
          public static void main(String[] args) {
              Car car = new Car();
              car.getCarDoor();
              car.getBasePlate();
              car.getCarFrame();
              car.make();
          }
      }
      

(3)创建者模式【Builder】

  • 将复杂对象的创建和属性的赋值相互分离

  • 忽略创建的过程和细节,只需要通过创建者操作即可

  • 举例:

    1. 新建 com.pattern.creational.builder 包,其中新建 Car 实体类

      package com.pattern.creational.builder;
      
      public class Car {
          private String carDoor;
          private String basePlate;
          private String carFrame;
      
          public String getCarDoor() { return carDoor; }
          public void setCarDoor(String carDoor) { this.carDoor = carDoor; }
      
          public String getBasePlate() { return basePlate; }
          public void setBasePlate(String basePlate) { this.basePlate = basePlate; }
      
          public String getCarFrame() { return carFrame; }
          public void setCarFrame(String carFrame) { this.carFrame = carFrame; }
          
          @Override
          public String toString() {
              return "Car{" +
                      "carDoor='" + carDoor + '\'' +
                      ", basePlate='" + basePlate + '\'' +
                      ", carFrame='" + carFrame + '\'' +
                      '}';
          }
      }
      
    2. 新建 Builder 抽象类,实现创建与构成的分离

      package com.pattern.creational.builder;
      
      public abstract class Builder {
          public abstract void buildCarDoor(String carDoor);
          public abstract void buildBasePlate(String basePlate);
          public abstract void buildCarFrame(String carFrame);
          public abstract Car makeCar();
      }
      
    3. 新建 CarBuilder 类,继承 Builder 类

      package com.pattern.creational.builder;
      
      public class CarBuilder extends Builder {
          private Car car = new Car();
          
          @Override
          public void buildCarDoor(String carDoor) { car.setCarDoor(carDoor); }
      
          @Override
          public void buildBasePlate(String basePlate) { car.setBasePlate(basePlate); }
      
          @Override
          public void buildCarFrame(String carFrame) { car.setCarFrame(carFrame); }
      
          @Override
          public Car makeCar() { return car; }
      }
      
    4. 新建 Engineer 类,表示工程师完成汽车生产

      package com.pattern.creational.builder;
      
      public class Engineer {
          private CarBuilder builder;
      
          public void setBuilder(CarBuilder builder) { this.builder = builder; }
      
          public Car makeCar(String carDoor, String basePlate, String carFrame) {
              builder.buildCarDoor(carDoor);
              builder.buildBasePlate(basePlate);
              builder.buildCarFrame(carFrame);
              return builder.makeCar();
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.creational.builder;
      
      public class Test {
          public static void main(String[] args) {
              CarBuilder builder = new CarBuilder();
              Engineer engineer = new Engineer();
              engineer.setBuilder(builder);
              Car car = engineer.makeCar("Car Door", "Base Plate", "Car Frame");
              System.out.println(car);
          }
      }
      

(4)原型模式【Prototype】

  • 用于创建重复的对象,能够保证创建对象的性能

  • 是创建对象的最佳方式

  • 举例:创建小猪佩奇的一家

    1. 新建 com.pattern.creational.prototype 包,其中新建 Pig 类

      package com.pattern.creational.prototype;
      
      public class Pig {
          private String name;
          private String doSomething;
      
          public String getName() { return name; }
          public void setName(String name) { this.name = name; }
      
          public String getDoSomething() { return doSomething; }
          public void setDoSomething(String doSomething) { this.doSomething = doSomething; }
      
          @Override
          public String toString() {
              return "Pig{" +
                      "name='" + name + '\'' +
                      ", doSomething='" + doSomething + '\'' +
                      '}' + super.toString();
          }
      }
      
    2. 新建 Test 类测试

      package com.pattern.creational.prototype;
      
      public class Test {
          public static void main(String[] args) {
              Pig peppa = new Pig();
              peppa.setName("peppa");
              peppa.setDoSomething("Eat cake");
              System.out.println(peppa);
      
              Pig george = new Pig();
              george.setName("george");
              george.setDoSomething("Sleep");
              System.out.println(george);
          }
      }
      

      此时并没有实现原型设计模式

    3. 修改 Pig 类,指定构造方法,实现 Cloneable 接口并重写 clone() 方法

      package com.pattern.creational.prototype;
      
      public class Pig implements Cloneable {
          public Pig() { System.out.println("Pig is initializing"); }
          
          private String name;
          private String doSomething;
      
          @Override
          protected Object clone() throws CloneNotSupportedException {
              return super.clone();
          }
      
          public String getName() { return name; }
          // 以下内容没有变化
      }
      
    4. 在 Test 类中使用原型设计模式创建对象

      package com.pattern.creational.prototype;
      
      public class Test {
          public static void main(String[] args) throws CloneNotSupportedException {
              Pig peppa = new Pig();
              peppa.setName("peppa");
              peppa.setDoSomething("Eat cake");
              System.out.println(peppa);
      
              Pig george = (Pig) peppa.clone();
              george.setName("george");
              george.setDoSomething("Sleep");
              System.out.println(george);
          }
      }
      

(5)单例模式【Singleton】

  • 可以在程序中保持一个实例对象
  • 减小内存开销
  • 既简单又复杂,有多种实现方法:懒加载、双重检查、静态内部类、饿汉式、枚举
  • 举例:
    • 新建 com.pattern.creational.singleton 包

a. 懒汉式(懒加载)

在需要使用对象时才会创建

  1. 新建 lazy 包,其中新建 LazySingleton 类

    package com.pattern.creational.singleton.lazy;
    
    public class LazySingleton {
        private static LazySingleton lazySingleton = null;
        private LazySingleton() {}
        public static LazySingleton getInstance() {
            if(lazySingleton == null)
                lazySingleton = new LazySingleton();
            return lazySingleton;
        }
    }
    
  2. 新建 Run 类,实现 Runnable 接口,从而可以使用多线程获取单例对象,

    package com.pattern.creational.singleton.lazy;
    
    public class Run implements Runnable {
        @Override
        public void run() {
            LazySingleton instance = LazySingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + " " + instance);
        }
    }
    
  3. 新建 Test 类测试

    package com.pattern.creational.singleton.lazy;
    
    public class Test {
        public static void main(String[] args) {
            Thread thread1 = new Thread(new Run());
            Thread thread2 = new Thread(new Run());
            thread1.start();
            thread2.start();
            System.out.println("Over");
        }
    }
    

b. 双重检查

通过两个 if 判定以及同步锁进行实现

  1. 新建 doublechecked 包,其中新建 DoubleCheckSingleton 类

    package com.pattern.creational.singleton.doublechecked;
    
    public class DoubleCheckSingleton {
        private static DoubleCheckSingleton doubleCheckSingleton;
        private DoubleCheckSingleton() {}
        public static DoubleCheckSingleton getInstance() {
            if(doubleCheckSingleton == null)
                synchronized (DoubleCheckSingleton.class) {
                    if (doubleCheckSingleton == null)
                        doubleCheckSingleton = new DoubleCheckSingleton();
                }
            return doubleCheckSingleton;
        }
    }
    

    多线程时,线程争抢资源、交替进行,可能会出现多个线程同时进入 getInstance() 方法中,添加同步锁后,使得只有一个线程可以继续进行

  2. 新建 Run 类

    package com.pattern.creational.singleton.doublechecked;
    
    public class Run implements Runnable {
        @Override
        public void run() {
            DoubleCheckSingleton instance = DoubleCheckSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + " " + instance);
        }
    }
    
  3. 新建 Test 类测试

    package com.pattern.creational.singleton.doublechecked;
    
    import com.pattern.creational.singleton.lazy.Run;
    
    public class Test {
        public static void main(String[] args) {
            Thread thread1 = new Thread(new com.pattern.creational.singleton.lazy.Run());
            Thread thread2 = new Thread(new Run());
            thread1.start();
            thread2.start();
            System.out.println("Over");
        }
    }
    

c. 静态内部类

在单例中,通过私有的静态内部类,创建单例对象

  1. 新建 staticinnerclass 包,其中新建 StaticInnerClassSingleton 类

    package com.pattern.creational.singleton.staticinnerclass;
    
    public class StaticInnerClassSingleton {
        private static class InnerClass {
            private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
        }
        private StaticInnerClassSingleton() {}
        public static StaticInnerClassSingleton getInstance() {
            return InnerClass.staticInnerClassSingleton;
        }
    }
    
  2. 新建 Run 类

    package com.pattern.creational.singleton.staticinnerclass;
    
    public class Run implements Runnable {
        @Override
        public void run() {
            StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + " " + instance);
        }
    }
    
  3. 新建 Test 类测试

    package com.pattern.creational.singleton.staticinnerclass;
    
    public class Test {
        public static void main(String[] args) {
            Thread thread1 = new Thread(new Run());
            Thread thread2 = new Thread(new Run());
            thread1.start();
            thread2.start();
            System.out.println("Over");
        }
    }
    

d. 饿汉式

在调用时创建单例对象,通过静态代码块或静态变量直接初始化

  1. 新建 hungry 包,其中新建 HungrySingleton 类

    
    

    两种写法:

    1. 静态代码块

      private static HungrySingleton hungrySingleton = null;
      static {
          hungrySingleton = new HungrySingleton();
      }
      
    2. 静态变量

      private static HungrySingleton hungrySingleton = new HungrySingleton();
      
  2. 新建 Run 类

    package com.pattern.creational.singleton.hungry;
    
    public class Run implements Runnable {
        @Override
        public void run() {
            HungrySingleton instance = HungrySingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + " " + instance);
        }
    }
    
  3. 新建 Test 类测试

    package com.pattern.creational.singleton.hungry;
    
    public class Test {
        public static void main(String[] args) {
            Thread thread1 = new Thread(new Run());
            Thread thread2 = new Thread(new Run());
            thread1.start();
            thread2.start();
            System.out.println("Over");
        }
    }
    

e. 枚举

枚举的方式实现单例模式是最佳的实现方式,可以有效防止对单例模式的破坏

  1. 新建 enumeration 包,其中新建 EnumSingleton 枚举

    package com.pattern.creational.singleton.enumeration;
    
    public enum EnumSingleton {
        INSTANCE;
        public static EnumSingleton getInstance() {
            return INSTANCE;
        }
    }
    
  2. 新建 Test 类测试

    package com.pattern.creational.singleton.enumeration;
    
    public class Test {
        public static void main(String[] args) {
            EnumSingleton singleton1 = EnumSingleton.getInstance();
            EnumSingleton singleton2 = EnumSingleton.getInstance();
            System.out.println(singleton1);
            System.out.println(singleton2);
            System.out.println(singleton1 == singleton2);
        }
    }
    

I. 序列化和反序列化的方式破坏单例模式

  • 通过流将单例对象序列化到文件当中,再反序列化读出

  • 最终通过反序列化的方式创建出一个对象,此时两个对象的地址不一致,即破坏了单例模式

  • 举例:

    1. 新建 destroyer 包,其中新建 Singleton 类,使用懒汉式,实现 Serializable

      package com.pattern.creational.singleton.destroyer;
      
      import java.io.Serializable;
      
      public class Singleton implements Serializable {
          private static Singleton singleton = null;
          private Singleton() {}
          public static Singleton getInstance() {
              if(singleton == null)
                  singleton = new Singleton();
              return singleton;
          }
      }
      
    2. 新建 TestSerializer 类测试

      package com.pattern.creational.singleton.destroyer;
      
      import java.io.*;
      
      public class TestSerializer {
          public static void main(String[] args) throws IOException, ClassNotFoundException {
              Singleton instance = Singleton.getInstance();
      
              ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton"));
              oos.writeObject(instance);
      
              ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("singleton")));
              Singleton objInstance = (Singleton) ois.readObject();
      
              System.out.println(instance);
              System.out.println(objInstance);
              System.out.println(instance == objInstance);
          }
      }
      

      根据输出结果可以发现,序列化与反序列化破坏了单例模式

    3. 修改 Singleton 类,通过枚举方式实现

      package com.pattern.creational.singleton.destroyer;
      
      import java.io.Serializable;
      
      public enum Singleton implements Serializable {
          INSTANCE;
          public static Singleton getInstance() {
              return INSTANCE;
          }
      }
      
    4. 重新运行 Test,发现此时单例模式并没有被破坏

    5. 为防止通过其他方法实现时单例模式被破坏,可以添加 readResolve() 方法,以懒汉式为例
      修改 Singleton 类

      package com.pattern.creational.singleton.destroyer;
      
      import java.io.Serializable;
      
      public class Singleton implements Serializable {
          private static Singleton singleton = null;
          // ...
          private Object readResolve() {
              return singleton;
          }
      }
      

      readResolve() 方法来源于反射机制,名称固定

II. 通过反射的方式破坏单例模式

  • 通过字节码对象创建构造器对象

  • 通过构造器对象初始化单例对象

    • 由于单例对象的构造方法是私有化的,因此需要调用构造器中的方法,赋予权限,创建单例对象
  • 举例:

    1. 在 com.pattern.creational.singleton.destroyer 包中新建 TestReflect 类,使用懒汉式方法

      package com.pattern.creational.singleton.destroyer;
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
      
      public class TestReflect {
          public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
              // 通过反射模式获取 instance
              // 创建字节码对象
              Class<Singleton> clz = Singleton.class;
              // 创建构造器对象
              Constructor<Singleton> constructor = clz.getDeclaredConstructor();
              // 赋予权限
              constructor.setAccessible(true);
              // 初始化单例对象
              Singleton clzInstance = (Singleton) constructor.newInstance();
              System.out.println(clzInstance);
              // 通过单例模式获取 instance
              Singleton singletonInstance = Singleton.getInstance();
              System.out.println(singletonInstance);
              System.out.println(clzInstance == singletonInstance);
          }
      }
      

      此时两种方法创建的单例并不同

    2. 修改 Singleton 类,使用枚举方法

      package com.pattern.creational.singleton.destroyer;
      
      public enum Singleton {
          INSTANCE;
          public static Singleton getInstance() {
              return INSTANCE;
          }
      }
      
    3. 修改 TestReflect 类,在创建构造方法时需要传入两个参数(String 和 int)

      package com.pattern.creational.singintleton.destroyer;
      
      import java.lang.reflect.Constructor;
      import java.lang.reflect.InvocationTargetException;
      
      public class TestReflect {
          public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
              // 通过反射模式获取 instance
              // 创建字节码对象
              Class<Singleton> clz = Singleton.class;
              // 创建构造器对象
              Constructor<Singleton> constructor = clz.getDeclaredConstructor(String.class, int.class);
              // 赋予权限
              constructor.setAccessible(true);
              // 初始化单例对象
              Singleton clzInstance = (Singleton) constructor.newInstance("string", 1);
              System.out.println(clzInstance);
              // 通过单例模式获取 instance
              Singleton singletonInstance = Singleton.getInstance();
              System.out.println(singletonInstance);
              System.out.println(clzInstance == singletonInstance);
          }
      }
      

      此时报错 Cannot reflectively create enum objects,说明在使用枚举时,不允许通过反射创建单例对象

    4. 对其他方法进行如下修改,以懒汉式为例
      修改 Singleton

      package com.pattern.creational.singleton.destroyer;
      
      import java.io.Serializable;
      
      public class Singleton implements Serializable {
          private static Singleton singleton = null;
          // 设置报错
          private Singleton() {
              if(singleton == null) {
                  throw new RuntimeException("Creating singleton objects through reflection is not allowed");
              }
          }
          public static Singleton getInstance() {
              if(singleton == null)
                  singleton = new Singleton();
              return singleton;
          }
          private Object readResolve() {
              return singleton;
          }
      }
      

0x04 结构型模式

  • 通常用来处理实体之间的关系,使得这些实体能够更好地协同工作。

    • 主要关注类和对象的组合关系
    • 继承的概念被用来组合接口和定义组合对象,获得新的功能方式
  • 在解决了对象的创建问题之后,对象的组成以及对象之间的依赖关系就成了开发人员关注的焦点,因为如何设计对象的结构、继承和依赖关系会影响到后续程序的维护性、代码的健壮性、耦合性等。

(6)外观模式【Facade】

  • 提供了一个统一的接口,用来访问子系统中的多个接口

  • 定义了一个高层接口,使子系统使用更容易

  • 举例:

    1. 新建 com.pattern.structural.facade 包,其中分别新建 OrderService 类、PayService 类、SelectFoodService 类

      package com.pattern.structural.facade;
      
      // 订单服务
      public class OrderService {
          public void makeOrder() {
              System.out.println("make order");
          }
      }
      
      package com.pattern.structural.facade;
      
      // 支付服务
      public class PayService {
          public void pay() {
              System.out.println("paying");
          }
          public boolean checkBalance() {
              System.out.println("checking balance");
              return true;
          }
      }
      
      package com.pattern.structural.facade;
      
      // 点餐服务
      public class SelectFoodService {
          public void select(String name) {
              System.out.println("Success: " + name);
          }
      }
      
    2. 新建 Food 类

      package com.pattern.structural.facade;
      
      public class Food {
          private String name;
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      }
      
    3. 新建 TakingSystem 类,作为最高层的类

      package com.pattern.structural.facade;
      
      public class TakingSystem {
          private OrderService orderService;
          private PayService payService;
          private SelectFoodService selectFoodService;
          public TakingSystem() {
              orderService = new OrderService();
              payService = new PayService();
              selectFoodService = new SelectFoodService();
          }
          public void orderTaking(Food food) {
              selectFoodService.select(food.getName());
              boolean flag = payService.checkBalance();
              if(flag) {
                  payService.pay();
                  orderService.makeOrder();
              }
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.structural.facade;
      
      public class Test {
          public static void main(String[] args) {
              Food food = new Food();
              food.setName("food");
              TakingSystem system = new TakingSystem();
              system.orderTaking(food); 
          }
      }
      

(7)适配器模式【Adapter】

  • 是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另外一个接口

  • 结合了两个独立接口的功能,可以使接口不兼容的类共同完成任务

  • 举例:

    1. 新建 com.pattern.structural.adapter 包,其中新建 MediaPlayer 接口和 AdvancedMediaPlayer 接口

      package com.pattern.structural.adapter;
      
      // 媒体播放器
      public interface MediaPlayer {
          public void play(String audioType, String fileName);
      }
      
      package com.pattern.structural.adapter;
      
      // 高级媒体播放器
      public interface AdvancedMediaPlayer {
          public void playVlc(String fileName);
          public void playMp4(String fileName);
      }
      
    2. 新建 VlcPlayer 类和 Mp4Player 类,实现 AdvancedMediaPlayer 接口

      package com.pattern.structural.adapter;
      
      public class VlcPlayer implements AdvancedMediaPlayer {
          @Override
          public void playVlc(String fileName) {
              System.out.println("Play .vlc file: " + fileName);
          }
      
          @Override
          public void playMp4(String fileName) {}
      }
      
      package com.pattern.structural.adapter;
      
      public class Mp4Player implements AdvancedMediaPlayer {
          @Override
          public void playVlc(String fileName) {}
      
          @Override
          public void playMp4(String fileName) {
              System.out.println("Play .mp4 file: " + fileName);
          }
      }
      
    3. 新建 MediaPlayerAdapter 类,实现 MediaPlayer 接口

      package com.pattern.structural.adapter;
      
      public class MediaPlayerAdapter implements MediaPlayer {
          private AdvancedMediaPlayer advancedMediaPlayer;
      
          public MediaPlayerAdapter(String audioType) {
              if (audioType.equalsIgnoreCase("vlc")) {
                  advancedMediaPlayer = new VlcPlayer();
              } else if (audioType.equalsIgnoreCase("mp4")) {
                  advancedMediaPlayer = new Mp4Player();
              }
          }
      
          @Override
          public void play(String audioType, String fileName) {
              if (audioType.equalsIgnoreCase("vlc")) {
                  advancedMediaPlayer.playVlc(fileName);
              } else if (audioType.equalsIgnoreCase("mp4")) {
                  advancedMediaPlayer.playMp4(fileName);
              }
          }
      }
      
    4. 新建 AudioPlayer 类,实现 MediaPlayer 接口

      package com.pattern.structural.adapter;
      
      public class AudioPlayer implements MediaPlayer {
          private MediaPlayerAdapter mediaPlayerAdapter;
          @Override
          public void play(String audioType, String fileName) {
              if(audioType.equalsIgnoreCase("mp3")) {
                  System.out.println("Play .mp3 file: " + fileName);
              } else if(audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {
                  mediaPlayerAdapter = new MediaPlayerAdapter(audioType);
                  mediaPlayerAdapter.play(audioType, fileName);
              }
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.structural.adapter;
      
      public class Test {
          public static void main(String[] args) {
              AudioPlayer audioPlayer = new AudioPlayer();
              audioPlayer.play("mp3", "music.mp3");
              audioPlayer.play("vlc", "media.vlc");
              audioPlayer.play("mp4", "video.mp4");
          }
      }
      

(8)桥接模式【Bridge】

  • 桥接是用于把抽象化和实现化解耦,使二者可以独立变化

  • 通过提供抽象化和实现化之间的桥接结构实现二者的解耦

  • 涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类

  • 举例:

    1. 新建 com.pattern.structural.bridge 包,其中新建 Shape 接口

      package com.pattern.structural.bridge;
      
      public interface Shape {
          public void draw(String tool);
      }
      
    2. 新建 Circle 类和 Square 类,实现 Shape 接口

      package com.pattern.structural.bridge;
      
      public class Circle implements Shape {
          @Override
          public void draw(String tool) {
              System.out.println("Use "+ tool +" to draw a circle");
          }
      }
      
      package com.pattern.structural.bridge;
      
      public class Square implements Shape {
          @Override
          public void draw(String tool) {
              System.out.println("Use " + tool + " to draw a square");
          }
      }
      
    3. 新建 Tools 抽象类

      package com.pattern.structural.bridge;
      
      public abstract class Tools {
          public Tools(Shape shape) {}
          public abstract void use();
      }
      
    4. 新建 Pen 类和 Pencil 类,继承 Tools 抽象类

      package com.pattern.structural.bridge;
      
      public class Pen extends Tools {
          private Shape shape;
      
          public Pen(Shape shape) {
              super(shape);
              this.shape = shape;
          }
      
          @Override
          public void use() {
              shape.draw("pen");
          }
      }
      
      package com.pattern.structural.bridge;
      
      public class Pencil extends Tools {
          private Shape shape;
      
          public Pencil(Shape shape) {
              super(shape);
              this.shape = shape;
          }
      
          @Override
          public void use() {
              shape.draw("pencil");
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.structural.bridge;
      
      public class Test {
          public static void main(String[] args) {
              Tools pen = new Pen(new Circle());
              pen.use();
              Tools pencil = new Pencil(new Square());
              pencil.use();
          }
      }
      

      此时,桥接体现在 Shape 接口与 Tools 抽象类并没有直接接触,但顺利的完成了合作

(9)组合模式【Composite】

  • 又称部分整体模式,用于把一组相似的对象当作一个单一的对象

  • 依据树形结构来组合对象,用来表示部分以及整体层次

  • 创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式

  • 举例:一个组织中员工的层次结构

    1. 新建 com.pattern.structural.composite 包,其中新建 Employee 类

      package com.pattern.structural.composite;
      
      import java.util.ArrayList;
      import java.util.List;
      
      public class Employee {
          private String name;
          private String id;
          private Long salary;
          private List<Employee> employeeList;
      
          public Employee(String name, String id, Long salary) {
              this.name = name;
              this.id = id;
              this.salary = salary;
              this.employeeList = new ArrayList<>();
          }
      
          public String getName() { return name; }
          public void setName(String name) { this.name = name; }
      
          public String getId() { return id; }
          public void setId(String id) { this.id = id;  }
      
          public Long getSalary() { return salary; }
          public void setSalary(Long salary) { this.salary = salary; }
      
          public List<Employee> getEmployeeList() { return employeeList; }
          public void setEmployeeList(List<Employee> employeeList) { this.employeeList = employeeList; }
      
          @Override
          public String toString() {
              return "Employee{" +
                      "name='" + name + '\'' +
                      ", id='" + id + '\'' +
                      ", salary=" + salary +
                      '}';
          }
      
          public void add(Employee employee) {
              employeeList.add(employee);
          }
          public void remove(Employee employee) {
              employeeList.remove(employee);
          }
      }
      
    2. 新建 Test 类测试

      package com.pattern.structural.composite;
      
      public class Test {
          public static void main(String[] args) {
              Employee boss = new Employee("boss", "001", 20000L);
              Employee manager = new Employee("manager", "002", 10000L);
              Employee worker1 = new Employee("worker", "003", 5000L);
              Employee worker2 = new Employee("worker", "004", 5000L);
      
              // 添加层级关系
              boss.add(manager);
              manager.add(worker1);
              manager.add(worker2);
      
              System.out.println(boss);
              for(Employee employee : boss.getEmployeeList()) {
                  System.out.println("Id: " + employee.getId() + "\tName: " + employee.getName() + "\tSalary: " + employee.getSalary());
                  for(Employee employee1 : employee.getEmployeeList()) {
                      System.out.println("Id: " + employee1.getId() + "\tName: " + employee1.getName() + "\tSalary: " + employee1.getSalary());
                  }
              }
          }
      }
      

(10)代理模式【Proxy】

  • 为对象提供一种代理,以控制这个对象的访问操作
  • 代理对象和目标对象之间起到中介作用
  • 可以保护和增强目标对象
  • 将代理对象与真实被调用的目标对象分离,降低了系统的耦合度,扩展性好
  • 举例:
    • 新建 com.pattern.structural.proxy 包

a. 静态代理

  1. 新建 staticproxy 包,其中新建 Order 类

    package com.pattern.structural.proxy.staticproxy;
    
    public class Order {
        private String info;
        private String id;
    
        public String getInfo() { return info; }
        public void setInfo(String info) { this.info = info; }
    
        public String getId() { return id; }
        public void setId(String id) { this.id = id; }
    
        @Override
        public String toString() {
            return "Order{" +
                    "info='" + info + '\'' +
                    ", id='" + id + '\'' +
                    '}';
        }
    }
    
  2. 新建 OrderDao 接口和 OrderService 接口

    package com.pattern.structural.proxy.staticproxy;
    
    public interface OrderDao {
        int insertOrder(Order order);
    }
    
    package com.pattern.structural.proxy.staticproxy;
    
    public interface OrderService {
        int saveOrder(Order order);
    }
    
  3. 新建 OrderDaoImpl 类和 OrderServiceImpl 类,分别实现 OrderDao 接口和 OrderService 接口

    package com.pattern.structural.proxy.staticproxy;
    
    public class OrderDaoImpl implements OrderDao {
        @Override
        public int insertOrder(Order order) {
            System.out.println("持久层" + order);
            return 0;
        }
    }
    
    package com.pattern.structural.proxy.staticproxy;
    
    public class OrderServiceImpl implements OrderService {
        private OrderDao orderDao;
        @Override
        public int saveOrder(Order order) {
            System.out.println("业务层");
            orderDao = new OrderDaoImpl();
            return orderDao.insertOrder(order);
        }
    }
    
  4. 新建 OrderServiceImplStaticProxy 类,作为静态代理类

    package com.pattern.structural.proxy.staticproxy;
    
    public class OrderServiceImplStaticProxy {
        private OrderService orderService;
        public int saveOrder(Order order) {
            orderService = new OrderServiceImpl();
            before();
            int i = orderService.saveOrder(order);
            System.out.println("代理对象");
            after();
            return i;
        }
        public void before() {
            System.out.println("代理对象开启事务");
        }
        public void after() {
            System.out.println("代理对象提交事务");
        }
    }
    
  5. 新建 Test 类测试

    package com.pattern.structural.proxy.staticproxy;
    
    public class Test {
        public static void main(String[] args) {
            Order order = new Order();
            order.setInfo("Information");
            order.setId("001");
    
            OrderServiceImplStaticProxy proxy = new OrderServiceImplStaticProxy();
            proxy.saveOrder(order);
        }
    }
    

b. 动态代理

  1. 新建 dynamicproxy 包,其中复制 staticproxy 中的所有类与接口

  2. 修改 OrderServiceImplStaticProxy 类为 OrderServiceImplDynamicProxy 类并重写

    package com.pattern.structural.proxy.dynamicproxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class OrderServiceImplDynamicProxy implements InvocationHandler {
        private Object service;
        public OrderServiceImplDynamicProxy(Object service) { this.service = service; }
        public Object bind() { return Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), this); }
        public void before() {
            System.out.println("代理对象开启事务");
        }
        public void after() {
            System.out.println("代理对象提交事务");
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object invoke = method.invoke(service, args);
            after();
            return invoke;
        }
    }
    
  3. 新建 Test 类测试

    package com.pattern.structural.proxy.dynamicproxy;
    
    public class Test {
        public static void main(String[] args) {
            Order order = new Order();
            order.setInfo("Information");
            order.setId("001");
            OrderService proxy = (OrderService) new OrderServiceImplDynamicProxy(new OrderServiceImpl()).bind();
            proxy.saveOrder(order);
        }
    }
    

(11)装饰模式【Decorator】

  • 在原有对象不做改变的基础上,将对象的功能附加上

  • 提供了比继承更有弹性的替代方案

  • 动态地给一个对象添加或撤销功能

  • 通过使用不同装饰类以及其排列组合可以实现不同效果

  • 举例:煎饼果子

    1. 新建 com.pattern.structural.decorator 包,其中新建 ABatterCake 抽象类

      package com.pattern.structural.decorator;
      
      public abstract class ABatterCake {
          protected abstract String getInfo();
          protected abstract int getCost();
      }
      
    2. 新建 BatterCake 类,继承 ABatterCake 抽象类

      package com.pattern.structural.decorator;
      
      public class BatterCake extends ABatterCake {
          @Override
          protected String getInfo() {
              return "Batter Cake";
          }
      
          @Override
          protected int getCost() {
              return 8;
          }
      }
      
    3. 新建 ADecorator 抽象类,继承 ABatterCake 抽象类,是装饰者

      package com.pattern.structural.decorator;
      
      public abstract class ADecorator extends ABatterCake {
          private ABatterCake aBatterCake;
          public ADecorator(ABatterCake aBatterCake) { this.aBatterCake = aBatterCake; }
          @Override
          protected String getInfo() {
              return this.aBatterCake.getInfo();
          }
      
          @Override
          protected int getCost() {
              return this.aBatterCake.getCost();
          }
      
          protected abstract void something();
      }
      
    4. 新建 EggDecorator 类和 SausageDecorator 类,都继承 ADecorator 抽象类

      package com.pattern.structural.decorator;
      
      public class EggDecorator extends ADecorator {
          public EggDecorator(ABatterCake aBatterCake) { super(aBatterCake); }
      
          @Override
          protected void something() {}
      
          @Override
          protected String getInfo() { return super.getInfo() + " Add an egg"; }
      
          @Override
          protected int getCost() { return super.getCost() + 2; }
      }
      
      package com.pattern.structural.decorator;
      
      public class SausageDecorator extends ADecorator {
      
          public SausageDecorator(ABatterCake aBatterCake) { super(aBatterCake); }
      
          @Override
          protected void something() {}
      
          @Override
          protected String getInfo() { return super.getInfo() + " Add a sausage"; }
      
          @Override
          protected int getCost() { return super.getCost() + 4; }
      }
      
    5. 新建 Test 类测试

      package com.pattern.structural.decorator;
      
      public class Test {
          public static void main(String[] args) {
              ABatterCake aBatterCake;
              aBatterCake = new BatterCake();
              aBatterCake = new EggDecorator(aBatterCake);
              aBatterCake = new EggDecorator(aBatterCake);
              aBatterCake = new SausageDecorator(aBatterCake);
              System.out.println(aBatterCake.getInfo() + ", the price is " + aBatterCake.getCost());
          }
      }
      

(12)享元模式【Flyweight】

  • 提供了减少对象数量从而改善应用所需的对象结构方式

  • 运用共享技术有效地支持大量细粒度的对象

  • 减少创建对象的数量,从而减少内存的占用,提升性能

  • 举例:

    1. 新建 com.pattern.structural.flyweight 包,其中新建 Employee 接口

      package com.pattern.structural.flyweight;
      
      public interface Employee {
          public void report();
      }
      
    2. 新建 Manager 类,实现 Employee 接口

      package com.pattern.structural.flyweight;
      
      public class Manager implements Employee {
          private String department;
          private String noteContent;
      
          public Manager(String department) { this.department = department; }
      
          public String getNoteContent() { return noteContent; }
      
          public void setNoteContent(String noteContent) { this.noteContent = noteContent; }
      
          @Override
          public void report() { System.out.println(this.noteContent); }
      }
      
    3. 新建 ManagementFactory 类

      package com.pattern.structural.flyweight;
      
      import java.util.*;
      
      public class ManagementFactory {
          private static final Map<String, Employee> EMPLOYEE_MAP = new HashMap<>();
          public static Employee getManager(String department) {
              Manager manager = (Manager) EMPLOYEE_MAP.get(department);
              if(manager == null) {
                  manager = new Manager(department);
                  System.out.println("New Manager: " + department);
                  String noteContent = department + " is here to report.";
                  manager.setNoteContent(noteContent);
                  System.out.println(department + " report completed.");
                  EMPLOYEE_MAP.put(department, manager);
              }
              return manager;
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.structural.flyweight;
      
      public class Test {
          private static final String[] departments = {"A", "B", "C"};
          public static void main(String[] args) {
              for (String department : departments) {
                  Employee manager = ManagementFactory.getManager(department);
                  manager.report();
              }
          }
      }
      

0x05 行为型模式

  • 用于在不同的实体间进行通信,为实体之间的通信提供更容易,更灵活的通信方法。

    • 主要关注对象之间的通信
  • 在对象的创建和对象的结构问题都解决了之后,就剩下对象的行为问题了。

  • 如果对象的行为设计的好,那么对象的行为就会更清晰,它们之间的协作效率就会提高。

(13)模板方法模式【Template Method】

  • 定义了一个算法的架构,并允许子类为一个或多个步骤的实现

  • 模板方法在子类不改变算法结构的情况下,重新定义算法的某些步骤

  • 实现一个算法不变的部分,并将可变的控件留给子类来完成

  • 子类中公共的行为抽出来并封装到一个公共父类中,提供代码复用性

  • 举例:制作课程,不同课程需要笔记情况不同

    1. 新建 com.pattern.behavioral.templatemethod 包,其中新建 AClass 抽象类

      package com.pattern.behavioral.templatemethod;
      
      public abstract class AClass {
          protected final void makeClass() {
              this.makePPT();
              if(this.flag()) {
                  this.makeNote();
                  this.isMakeNote();
              }
              this.makeVideo();
          }
          public final void makePPT() { System.out.println("Make PPT"); }
          public final void makeNote() { System.out.println("Make Note"); }
          public final void makeVideo() { System.out.println("Make Video"); }
          protected boolean flag() { return false; }
          public abstract void isMakeNote();
      }
      
    2. 新建 JavaClass 类和 Python 类,都继承 AClass 抽象类

      package com.pattern.behavioral.templatemethod;
      
      public class JavaClass extends AClass {
          private boolean flag;
      
          public JavaClass(boolean flag) { this.flag = flag; }
      
          @Override
          protected boolean flag() { return this.flag; }
      
          @Override
          public void isMakeNote() { System.out.println("Java Class's Note"); }
      }
      
      package com.pattern.behavioral.templatemethod;
      
      public class PythonClass extends AClass {
          @Override
          protected boolean flag() { return super.flag(); }
      
          @Override
          public void isMakeNote() { System.out.println("Python Class's Note"); }
      }
      
    3. 新建 Test 类测试

      package com.pattern.behavioral.templatemethod;
      
      public class Test {
          public static void main(String[] args) {
              AClass aClass;
      
              aClass = new JavaClass(true);
              aClass.makeClass();
              System.out.println("--------------");
              aClass = new PythonClass();
              aClass.makeClass();
          }
      }
      

(14)迭代器模式【Iterator】

  • 提供方法,顺序访问集合对象中的各个元素,同时不暴露对象内部表示

  • 为遍历不同的集合结构提供统一的接口,分离了集合对象的遍历行为

  • 举例:

    1. 新建 com.pattern.behavioral.iterator 包,其中新建 Iterator 接口,表示迭代器

      package com.pattern.behavioral.iterator;
      
      public interface Iterator {
          public boolean hasNext();
          public Object next();
      }
      
    2. 新建 Container 接口,表示容器

      package com.pattern.behavioral.iterator;
      
      public interface Container {
          public Iterator getIterator();
      }
      
    3. 新建 NameContainer 类,表示实现容器

      package com.pattern.behavioral.iterator;
      
      public class NameContainer implements Container {
          public String[] names = {"Alex", "Bob", "Charles"};
          @Override
          public Iterator getIterator() {
              return new NameIterator();
          }
          private class NameIterator implements Iterator {
              int index;
              @Override
              public boolean hasNext() {
                  return index < names.length;
              }
      
              @Override
              public Object next() {
                  if(this.hasNext()) {
                      return names[index++];
                  }
                  return null;
              }
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.iterator;
      
      public class Test {
          public static void main(String[] args) {
              Container container = new NameContainer();
              for(Iterator iterator = container.getIterator(); iterator.hasNext();) {
                  String name = (String) iterator.next();
                  System.out.println("Name: " + name);
              }
          }
      }
      

(15)策略模式【Strategy】

  • 定义了算法并分别封装起来,之间可以相互替换,使算法的变化不会影响使用算法的用户

  • 对于使用了大量 if...else... 语句的情况可以使用策略模式进行替换

  • 提高算法的保密性和安全性

  • 举例:两数计算

    1. 新建 com.pattern.behavioral.strategy 包,其中新建 Strategy 接口

      package com.pattern.behavioral.strategy;
      
      public interface Strategy {
          public int operation(int num1, int num2);
      }
      
    2. 新建 AddStrategy 类和 SubStrategy 类,都实现 Strategy 接口

      package com.pattern.behavioral.strategy;
      
      public class AddStrategy implements Strategy {
          @Override
          public int operation(int num1, int num2) {
              return num1 + num2;
          }
      }
      
      package com.pattern.behavioral.strategy;
      
      public class SubStrategy implements Strategy {
          @Override
          public int operation(int num1, int num2) {
              return num1 - num2;
          }
      }
      
    3. 新建 Operation 类

      package com.pattern.behavioral.strategy;
      
      public class Operation {
          private Strategy strategy;
      
          public Operation(Strategy strategy) {
              this.strategy = strategy;
          }
          public int execute(int num1, int num2) {
              return strategy.operation(num1, num2);
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.strategy;
      
      public class Test {
          public static void main(String[] args) {
              Operation operation;
              operation = new Operation(new AddStrategy());
              System.out.println("2 + 1 = " + operation.execute(2, 1));
              operation = new Operation(new SubStrategy());
              System.out.println("2 - 1 = " + operation.execute(2, 1));
          }
      }
      

(16)解释器模式【Interpreter】

  • 通过给定的语言定义其语法和行为并定义解释器

    • 解释器用来解释语言中的句子
  • 适用于某个类型问题触发频次高,如处理日志和不同日志格式

  • 举例:

    1. 新建 com.pattern.behavioral.interpreter 包,其中新建 Expression 接口

      package com.pattern.behavioral.interpreter;
      
      public interface Expression {
          public boolean interpret(String context);
      }
      
    2. 新建 TerminalExpression 类,实现 Expression 接口

      package com.pattern.behavioral.interpreter;
      
      public class TerminalExpression implements Expression {
          private String data;
          public TerminalExpression(String data) { this.data = data; }
          @Override
          public boolean interpret(String context) {
              return context.contains(data);
          }
      }
      
    3. 新建 OrExpression 类和 AndExpression 类,都实现 Expression 接口

      package com.pattern.behavioral.interpreter;
      
      public class OrExpression implements Expression {
          private Expression expression1;
          private Expression expression2;
      
          public OrExpression(Expression expression1, Expression expression2) {
              this.expression1 = expression1;
              this.expression2 = expression2;
          }
      
          @Override
          public boolean interpret(String context) {
              return expression1.interpret(context) || expression2.interpret(context);
          }
      }
      
      
      package com.pattern.behavioral.interpreter;
      
      public class AndExpression implements Expression {
          private Expression expression1;
          private Expression expression2;
      
          public AndExpression(Expression expression1, Expression expression2) {
              this.expression1 = expression1;
              this.expression2 = expression2;
          }
      
          @Override
          public boolean interpret(String context) {
              return expression1.interpret(context) && expression2.interpret(context);
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.interpreter;
      
      public class Test {
          public static void main(String[] args) {
              Expression Alex = new TerminalExpression("Alex");
              Expression Bob = new TerminalExpression("Bob");
              OrExpression or = new OrExpression(Alex, Bob);
              AndExpression and = new AndExpression(Alex, Bob);
      
              System.out.println(or.interpret("Alex"));
              System.out.println(and.interpret("Alex Bob"));
          }
      }
      

(17)观察者模式【Observer】

  • 当对象之间存在一对多关系时,使用观察者模式,当一个对象被修改时,会自动通知依赖它的对象

  • 使多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新

  • 举例:

    1. 新建 com.pattern.behavioral.observer 包,其中新建 Subject 类

      package com.pattern.behavioral.observer;
      
      import java.util.*;
      
      public class Subject {
          private List<Observer> observerList = new ArrayList();
          private int state;
      
          public int getState() { return state; }
          public void setState(int state) {
              this.state = state;
              notifyObservers();
          }
      
          public void binding(Observer observer) { observerList.add(observer); }
          public void notifyObservers() {
              for (Observer observer : observerList) {
                  observer.update();
              }
          }
      }
      
    2. 新建 Observer 抽象类

      package com.pattern.behavioral.observer;
      
      public abstract class Observer {
          protected Subject subject;
          public abstract void update();
      }
      
    3. 新建 HexObserver 类和 BinaryObserver 类,都继承 Observer 抽象类

      package com.pattern.behavioral.observer;
      
      public class HexObserver extends Observer {
          public HexObserver(Subject subject) {
              this.subject = subject;
              this.subject.binding(this);
          }
          @Override
          public void update() {
              System.out.println("Hex String: " + Integer.toHexString(subject.getState()));
          }
      }
      
      package com.pattern.behavioral.observer;
      
      public class BinaryObserver extends Observer {
          public BinaryObserver(Subject subject) {
              this.subject = subject;
              this.subject.binding(this);
          }
          @Override
          public void update() {
              System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.observer;
      
      public class Test {
          public static void main(String[] args) {
              Subject subject = new Subject();
              new HexObserver(subject);
              new BinaryObserver(subject);
              System.out.println("Number is 15");
              subject.setState(15);
          }
      }
      

(18)备忘录模式【Memento】

  • 在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态

  • 允许用户取消不确定或错误的操作并恢复到原来的状态

  • 举例:

    1. 新建 com.pattern.behavioral.memento 包,其中新建 Order 类

      package com.pattern.behavioral.memento;
      
      public class Order {
          private String state;
      
          public Order(String state) { this.state = state; }
      
          public String getState() { return state; }
      }
      
    2. 新建 Memento 类

      package com.pattern.behavioral.memento;
      
      public class Memento {
          private String state;
      
          public String getState() { return state; }
          public void setState(String state) { this.state = state; }
      
          public Order saveStateToOrder() { return new Order(state); }
          public void getStateFromOrder(Order order) { state = order.getState(); }
      }
      
    3. 新建 Container 类

      package com.pattern.behavioral.memento;
      
      import java.util.*;
      
      public class Container {
          private List<Order> orderList = new ArrayList<>();
          public void addOrder(Order order) {
              orderList.add(order);
          }
          public Order getOrder(int index) {
              return orderList.get(index);
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.memento;
      
      public class Test {
          public static void main(String[] args) {
              Memento memento = new Memento();
              Container container = new Container();
              
              memento.setState("Step 1");
              container.addOrder(memento.saveStateToOrder());
              memento.setState("Step 2");
              container.addOrder(memento.saveStateToOrder());
              memento.setState("Step 3");
              container.addOrder(memento.saveStateToOrder());
              
              memento.getStateFromOrder(container.getOrder(0));
              System.out.println(memento.getState());
              memento.getStateFromOrder(container.getOrder(1));
              System.out.println(memento.getState());
              memento.getStateFromOrder(container.getOrder(2));
              System.out.println(memento.getState());
          }
      }
      

(19)命令模式【Command】

  • 将一个请求封装成一个对象,从而可以用不同的请求对客户进行参数化

  • 减少行为请求者和行为实现者之间的耦合

  • 举例:通过经理人买卖股票

    1. 新建 com.pattern.behavioral.command 包,其中新建 Order 接口

      package com.pattern.behavioral.command;
      
      public interface Order {
          public void execute();
      }
      
    2. 新建 Stock 类

      package com.pattern.behavioral.command;
      
      public class Stock {
          private String name = "AAAA";
          private int count = 100;
      
          public void purchase() {
              System.out.println("Purchase " + count + " shares of " + name + " stock.");
          }
          public void sell() {
              System.out.println("Sell " + count + " shares of " + name + " stock.");
          }
      }
      
    3. 新建 PurchaseStock 类和 SellStock 类,都实现 Order 类

      package com.pattern.behavioral.command;
      
      public class PurchaseStock implements Order {
          private Stock stock;
      
          public PurchaseStock(Stock stock) { this.stock = stock; }
      
          @Override
          public void execute() { stock.purchase(); }
      }
      
      package com.pattern.behavioral.command;
      
      public class SellStock implements Order {
          private Stock stock;
      
          public SellStock(Stock stock) { this.stock = stock; }
      
          @Override
          public void execute() { stock.sell(); }
      }
      
    4. 新建 Broker 类

      package com.pattern.behavioral.command;
      
      import java.util.*;
      
      public class Broker {
          List<Order> orderList = new ArrayList<>();
          public void takeOrder(Order order) { orderList.add(order); }
          public void placeOrders() {
              for (Order order : orderList) {
                  order.execute();
              }
              orderList.clear();
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.behavioral.command;
      
      public class Test {
          public static void main(String[] args) {
              Stock aStock = new Stock();
              
              PurchaseStock purchaseStock = new PurchaseStock(aStock);
              SellStock sellStock = new SellStock(aStock);
              
              Broker broker = new Broker();
              broker.takeOrder(purchaseStock);
              broker.takeOrder(sellStock);
              
              broker.placeOrders();
          }
      }
      

(20)调停者模式【Mediator】

  • 用来降低对多个对象和类之间的通信复杂性

    • “调停者”类通常处理不同类之间的通信,并支持松耦合,使代码易于维护
  • 对象和对象之间存在大量的关联关系,容易导致系统的结构变得很复杂

  • 举例:

    1. 新建 com.pattern.behavioral.mediator 包,其中新建 User 类

      package com.pattern.behavioral.mediator;
      
      public class User {
          private String name;
      
          public String getName() { return name; }
          public void setName(String name) { this.name = name; }
      
          public void sendMessage(String message) { Role.work(this, message); }
      }
      
    2. 新建 Role 类

      package com.pattern.behavioral.mediator;
      
      public class Role {
          public static void work(User user, String message) {
              System.out.println("User: " + user.getName() + " message: " + message);
          }
      }
      
    3. 新建 Test 类测试

      package com.pattern.behavioral.mediator;
      
      public class Test {
          public static void main(String[] args) {
              User user = new User();
              user.setName("Alex");
              user.sendMessage("Hello");
              user.setName("Bob");
              user.sendMessage("World");
          }
      }
      

(21)职责链模式【Chain of Responsibility】

  • 为请求创建了一个接收者对象的链,对请求的发送者和接收者进行解耦

  • 通常每个接收者都包含对另一个接收者的引用,如果当前接收者不能处理次请求,则会将同一个请求传递到下一个接收者

  • 将对象连成链,从而防止请求发送者和接收者耦合在一起

  • 举例:

    1. 新建 com.pattern.behavioral.chain 包,其中新建 AbstractLogger 抽象类

      package com.pattern.behavioral.chain;
      
      public abstract class AbstractLogger {
          public static int INFO = 1;
          public static int DEBUG = 2;
          public static int ERROR = 3;
      
          protected AbstractLogger nextLogger;
          protected int level;
      
          public void setNextLogger(AbstractLogger nextLogger) { this.nextLogger = nextLogger; }
      
          public void logMessage(int level, String message) {
              if(this.level <= level) { write(message); }
              if(nextLogger != null) { nextLogger.logMessage(level, message); }
          }
          protected abstract void write(String message);
      }
      
    2. 新建 InfoLogger 类、DebugLogger 类、ErrorLogger 类,都实现 AbstractLogger 抽象类

      package com.pattern.behavioral.chain;
      
      public class InfoLogger extends AbstractLogger {
          public InfoLogger(int level) { this.level = level; }
          @Override
          protected void write(String message) {
              System.out.println("INFO: " + message);
          }
      }
      
      package com.pattern.behavioral.chain;
      
      public class DebugLogger extends AbstractLogger {
          public DebugLogger(int level) { this.level = level; }.level = level;
          }
          @Override
          protected void write(String message) {
              System.out.println("DEBUG: " + message);
          }
      }
      
      package com.pattern.behavioral.chain;
      
      public class ErrorLogger extends AbstractLogger { this.level = level; }
          @Override
          protected void write(String message) {
              System.out.println("ERROR: " + message);
          }
      }
      
    3. 新建 Test 类测试

      package com.pattern.behavioral.chain;
      
      public class Test {
          // 设置职责链
          public static AbstractLogger getChainOfLogger() {
              AbstractLogger infoLogger = new InfoLogger(AbstractLogger.INFO);
              AbstractLogger debugLogger = new DebugLogger(AbstractLogger.DEBUG);
              AbstractLogger errorLogger = new ErrorLogger(AbstractLogger.ERROR);
              infoLogger.setNextLogger(debugLogger);
              debugLogger.setNextLogger(errorLogger);
              return infoLogger;
          }
      
          public static void main(String[] args) {
              AbstractLogger logger = getChainOfLogger();
              logger.logMessage(1, "information");
              logger.logMessage(2, "debug information");
              logger.logMessage(3, "error information");
          }
      }
      

(22)访问者模式【Visitor】

  • 元素的执行算法可以随着访问者改变而改变

  • 元素对象已接受访问者对象,此时访问者对象就可以处理元素对象上的操作

  • 将数据结构与数据操作分离

  • 举例:

    1. 新建 com.pattern.behavioral.visitor 包,其中新建 ComputerPart 接口和 ComputerPartVisitor 接口

      package com.pattern.behavioral.visitor;
      
      public interface ComputerPart {
          public void accept(ComputerPartVisitor visitor);
      }
      
      package com.pattern.behavioral.visitor;
      
      public interface ComputerPartVisitor {
          void visit(Keyboard keyboard);
          void visit(Mouse mouse);
          void visit(Computer computer);
      }
      
    2. 新建 Keyboard 类和 Mouse 类,都实现 ComputerPart 接口

      package com.pattern.behavioral.visitor;
      
      public class Keyboard implements ComputerPart {
          @Override
          public void accept(ComputerPartVisitor visitor) {
              visitor.visit(this);
          }
      }
      
      package com.pattern.behavioral.visitor;
      
      public class Mouse implements ComputerPart {
          @Override
          public void accept(ComputerPartVisitor visitor) {
              visitor.visit(this);
          }
      }
      
    3. 新建 Computer 类,实现 ComputerPart 接口

      package com.pattern.behavioral.visitor;
      
      public class Computer implements ComputerPart {
          ComputerPart[] parts = new ComputerPart[]{new Keyboard(), new Mouse()};
          @Override
          public void accept(ComputerPartVisitor visitor) {
              for (ComputerPart part : parts) {
                  part.accept(visitor);
              }
              visitor.visit(this);
          }
      }
      
    4. 新建 ComputerDisplayVisitor 类,实现 ComputerPartVisitor 接口

      package com.pattern.behavioral.visitor;
      
      public class ComputerDisplayVisitor implements ComputerPartVisitor {
          @Override
          public void visit(Keyboard keyboard) {
              System.out.println("Add Keyboard" + keyboard);
          }
      
          @Override
          public void visit(Mouse mouse) {
              System.out.println("Add Mouse: " + mouse);
          }
      
          @Override
          public void visit(Computer computer) {
              System.out.println("Computer assembly completed: " + computer);
          }
      }
      
    5. 新建 Test 类测试

      package com.pattern.behavioral.visitor;
      
      public class Test {
          public static void main(String[] args) {
              ComputerPart computer = new Computer();
              computer.accept(new ComputerDisplayVisitor());
          }
      }
      

(23)状态模式【State】

  • 类的行为基于其状态进行改变

  • 允许对象在内部状态发生改变时改变其行为,对象的行为依赖于其状态

  • 举例:

    1. 新建 com.pattern.behavioral.state 包,其中新建 Context 类

      package com.pattern.behavioral.state;
      
      public class Context {
          private State state;
      
          public Context(State state) { state = null; }
      
          public State getState() { return state; }
          public void setState(State state) { this.state = state; }
      }
      
    2. 新建 State 接口

      package com.pattern.behavioral.state;
      
      public interface State {
          public void operator(Context context);
      }
      
    3. 新建 StartState 类和 EndState 类,都实现 State 接口

      package com.pattern.behavioral.state;
      
      public class StartState implements State {
          @Override
          public void operator() {
              System.out.println("Start...");
              context.setState(this);
          }
      
          @Override
          public String toString() {
              return "Running";
          }
      }
      
      package com.pattern.behavioral.state;
      
      public class EndState implements State {
          @Override
          public void operator(Context context) {
              System.out.println("End...");
              context.setState(this);
          }
      
          @Override
          public String toString() {
              return "Stopping...";
          }
      }
      
    4. 新建 Test 类测试

      package com.pattern.behavioral.state;
      
      public class Test {
          public static void main(String[] args) {
              Context context = new Context();
      
              State start = new StartState();
              start.operator(context);
              System.out.println(context.getState().toString());
      
              State end = new EndState();
              end.operator(context);
              System.out.println(context.getState().toString());
          }
      }
      

-End-

posted @ 2023-10-02 20:38  SRIGT  阅读(13)  评论(0编辑  收藏  举报