无苦集灭道 无智亦无得|

园龄:粉丝:关注:

2023-10-02 20:38阅读: 14评论: 0推荐: 0

设计模式

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-

本文作者:SRIGT

本文链接:https://www.cnblogs.com/SRIGT/p/17740413.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   SRIGT  阅读(14)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起