设计模式
0x01 设计模式概述
- 代表了代码的最佳实践
- 设计模式是很多被反复使用并知晓的,主要是对代码和经验的总结
- 设计模式是为了复用代码,使代码更容易被理解,保证代码可靠性
- 面向接口编程
- 优先使用对象组合,而非继承关系
以下代码示例均采用 Java 语言(JDK 18)
0x02 七大基本原则
(1)开闭原则【Open Closed Principle,OCP】
-
对扩展开放,对修改关闭
-
使用抽象进行构建,使用实现扩展细节
-
面向抽象编程
-
提高软件系统的可复用性和可维护性
-
举例:人类的基础行为和身份带来的特有行为
-
新建 com.dp.principle.ocp 包,其中新建 Human 接口
正常人类行为包括吃饭和睡觉package com.dp.principle.ocp; public interface Human { public void eat(); public void sleep(); }
-
新建 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."); } }
-
新建 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(); } }
至此已经简单地实现了接口的功能
-
为实现 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 中对扩展开放 -
在 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】
-
依赖倒转原则是开闭原则的基础,针对接口进行编程
-
依赖抽象,而不是具体的实现
-
可以减少类之间的耦合性,提高系统稳定性和代码可读性、可维护性,降低修改程序所造成的风险
-
举例:同类人在完成基础人类行为基础上,按照各自具体角色进行特定行为
-
新建 com.dp.principle.dip 包,其中新建 Human 接口
package com.dp.principle.dip; public interface Human { public void eat(); public void sleep(); }
-
新建 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(); }
至此实现了针对接口编程以及依赖抽象
-
新建 JavaProgrammer 类,作为具体的程序员,继承 Programmer 类并重写
work()
方法package com.dp.principle.dip; public class JavaProgrammer extends Programmer { @Override public void work() { System.out.println("JavaProgrammer is working."); } }
-
新建 TestProgrammer 类
package com.dp.principle.dip; public class TestProgrammer extends Programmer { @Override public void work() { System.out.println("TestProgrammer is working."); } }
-
新建 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】
-
一个类、接口、方法仅负责一项职责
-
降低了程序的复杂度与程序修改带来的风险,提高程序可维护性
-
举例:不同类型的行为进行分类设计
-
新建 com.dp.principle.srp 包,其中新建 Human 接口
package com.dp.principle.dip; public interface Human { public void eat(); public void sleep(); }
-
新建 Programmer 抽象类,实现 Human 接口
package com.dp.principle.srp; public abstract class Programmer implements Human { public abstract void work(); }
-
新建 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."); } }
-
新建 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(); } }
-
当在 JavaProgrammer 类中添加新的订外卖方法时,该类就出现了两个职责:工作、订外卖,此时违背了单一职责原则,需要另外新建一个类负责订外卖职责
新建 Order 类,local()
方法表示“堂食”,take()
方法表示“外卖”package com.dp.principle.srp; public class Order { public void local() { System.out.println("堂食"); } public void take() { System.out.println("外卖"); } }
-
在 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(); } }
-
在 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】
-
使用多个接口
-
尽量细化接口,接口中的方法尽可能少
-
符合低耦合的设计思想,提供了可扩展性和可维护性
-
举例:将人类的基础行为分别设计
-
新建 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(); }
-
-
新建 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."); } }
-
新建 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】
-
又称最少知识原则,一个对象应对其他对象保持最少的了解
-
降低类与类之间的耦合关系
-
强调只与“朋友”(成员变量、方法参数等)交流
-
举例:老板给项目经理开会,由项目经理传达任务
-
新建 com.dp.principle.lod 包,其中新建 Human 接口
package com.dp.principle.lod; public interface Human { }
-
新建 Programmer 抽象类实现 Human 接口
package com.dp.principle.lod; public abstract class Programmer implements Human { public abstract void work(); }
-
新建 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."); } }
-
新建 Manager 接口,继承 Human 接口
package com.dp.principle.lod; public interface Manager extends Human { }
-
新建 Boss 类实现 Manager 接口,添加“开会”方法
package com.dp.principle.lod; public class Boss implements Manager { public void meet() { System.out.println("Boss is meeting."); } }
-
新建 TeamLeader 类实现 Manager 接口,添加“分配工作”方法
package com.dp.principle.lod; public class TeamLeader implements Manager { public void assign() { System.out.println("TeamLeader is assigning tasks."); } }
-
在 Boss 接口中,修改
meet()
方法,以成员变量的方式传递 TeamLeader 接口,从而实现 Boss 通过 TeamLeader 分配工作public void meet(TeamLeader teamLeader) { System.out.println("Boss is meeting."); teamLeader.assign(); }
-
在 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(); } } }
-
新建 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 的补充
-
可以增加程序的健壮性
-
举例:老师给学生留作业
-
新建 com.dp.principle.lsp 包,其中新建 Teacher 类
package com.dp.principle.lsp; public class Teacher { public int fun1(int a, int b) { return a+b; } }
-
新建 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; } }
-
新建 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)); } }
此时已经违背了里氏替换原则
-
为防止子类不小心重写父类方法,在此新建 Human 类
package com.dp.principle.lsp; public class Human { }
-
设置 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()
,注入 Teacherpackage 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; } }
-
-
修改 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】
-
尽量使用对象的合成或聚合的方式,而非使用继承达到软件复用的目的
-
使系统更加灵活,降低类与类之间的耦合度
- 一个类的变化对其他类造成的影响相对较小
-
举例:老师通知学生家长开会
-
新建 com.dp.principle.carp 包,其中新建 Teacher 类
package com.dp.principle.carp; public class Teacher { public void call() { System.out.println("Call Alex's parents."); } }
-
新建 Student 类
package com.dp.principle.carp; public class Student { public void notifyMeeting() { System.out.println("Notify parent to attend parent meeting."); } }
-
新建 Parent 类
package com.dp.principle.carp; public class Parent { public void meeting() { System.out.println("Attend."); } }
-
新建 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(); } }
此时并没有达到合成复用原则,仅是达到基础目的,仍存在多处不足
-
新建 Notify 接口
package com.dp.principle.carp; public interface Notify { }
-
新建 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(); } }
-
新建 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(); } }
-
修改 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(); } } }
-
修改 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 种设计模式中
-
由一个工厂决定创建哪种产品类型的实例
-
举例:
-
新建 com.pattern.other.simplefactory 包,其中新建 Course 类
package com.pattern.other.simplefactory; public abstract class Course { public abstract void make(); }
-
新建 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."); } }
-
新建 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; } }
-
新建 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】
-
定义一个接口或一个抽象的工厂类,使其实现类来决定创建哪一个实例对象
-
根据每个工厂不同的方法,来产生不同的所需要的对象
-
举例:生产课程(同系列对象)
-
新建 com.pattern.creational.factorymethod 包,其中新建 Course 抽象类
package com.pattern.creational.factorymethod; public abstract class Course { public abstract void make(); }
-
新建 CourseFactory 抽象类
package com.pattern.creational.factorymethod; public abstract class CourseFactory { public abstract Course getCourse(); }
-
新建 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(); } }
-
新建 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(); } }
-
新建 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】
-
抽象工厂模式提供了创建一系列相关或互相依赖对象的接口
-
类似公司下的产品,产品不同系列
-
举例:生产汽车
-
新建 com.pattern.creational.abstractfactory 包
-
新建 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."); } }
-
新建 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."); } }
-
新建 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."); } }
-
新建 CarFactory 接口
package com.pattern.creational.abstractfactory; public interface CarFactory { public CarDoor getCarDoor(); public BasePlate getBasePlate(); public CarFrame getFrame(); public void make(); }
-
新建 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!"); } }
-
新建 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】
-
将复杂对象的创建和属性的赋值相互分离
-
忽略创建的过程和细节,只需要通过创建者操作即可
-
举例:
-
新建 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 + '\'' + '}'; } }
-
新建 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(); }
-
新建 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; } }
-
新建 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(); } }
-
新建 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】
-
用于创建重复的对象,能够保证创建对象的性能
-
是创建对象的最佳方式
-
举例:创建小猪佩奇的一家
-
新建 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(); } }
-
新建 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); } }
此时并没有实现原型设计模式
-
修改 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; } // 以下内容没有变化 }
-
在 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. 懒汉式(懒加载)
在需要使用对象时才会创建
-
新建 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; } }
-
新建 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); } }
-
新建 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
判定以及同步锁进行实现
-
新建 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()
方法中,添加同步锁后,使得只有一个线程可以继续进行 -
新建 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); } }
-
新建 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. 静态内部类
在单例中,通过私有的静态内部类,创建单例对象
-
新建 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; } }
-
新建 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); } }
-
新建 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. 饿汉式
在调用时创建单例对象,通过静态代码块或静态变量直接初始化
-
新建 hungry 包,其中新建 HungrySingleton 类
两种写法:
-
静态代码块
private static HungrySingleton hungrySingleton = null; static { hungrySingleton = new HungrySingleton(); }
-
静态变量
private static HungrySingleton hungrySingleton = new HungrySingleton();
-
-
新建 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); } }
-
新建 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. 枚举
枚举的方式实现单例模式是最佳的实现方式,可以有效防止对单例模式的破坏
-
新建 enumeration 包,其中新建 EnumSingleton 枚举
package com.pattern.creational.singleton.enumeration; public enum EnumSingleton { INSTANCE; public static EnumSingleton getInstance() { return INSTANCE; } }
-
新建 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. 序列化和反序列化的方式破坏单例模式
-
通过流将单例对象序列化到文件当中,再反序列化读出
-
最终通过反序列化的方式创建出一个对象,此时两个对象的地址不一致,即破坏了单例模式
-
举例:
-
新建 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; } }
-
新建 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); } }
根据输出结果可以发现,序列化与反序列化破坏了单例模式
-
修改 Singleton 类,通过枚举方式实现
package com.pattern.creational.singleton.destroyer; import java.io.Serializable; public enum Singleton implements Serializable { INSTANCE; public static Singleton getInstance() { return INSTANCE; } }
-
重新运行 Test,发现此时单例模式并没有被破坏
-
为防止通过其他方法实现时单例模式被破坏,可以添加
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. 通过反射的方式破坏单例模式
-
通过字节码对象创建构造器对象
-
通过构造器对象初始化单例对象
- 由于单例对象的构造方法是私有化的,因此需要调用构造器中的方法,赋予权限,创建单例对象
-
举例:
-
在 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); } }
此时两种方法创建的单例并不同
-
修改 Singleton 类,使用枚举方法
package com.pattern.creational.singleton.destroyer; public enum Singleton { INSTANCE; public static Singleton getInstance() { return INSTANCE; } }
-
修改 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
,说明在使用枚举时,不允许通过反射创建单例对象 -
对其他方法进行如下修改,以懒汉式为例
修改 Singletonpackage 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】
-
提供了一个统一的接口,用来访问子系统中的多个接口
-
定义了一个高层接口,使子系统使用更容易
-
举例:
-
新建 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); } }
-
新建 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; } }
-
新建 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(); } } }
-
新建 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】
-
是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成客户希望的另外一个接口
-
结合了两个独立接口的功能,可以使接口不兼容的类共同完成任务
-
举例:
-
新建 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); }
-
新建 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); } }
-
新建 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); } } }
-
新建 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); } } }
-
新建 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】
-
桥接是用于把抽象化和实现化解耦,使二者可以独立变化
-
通过提供抽象化和实现化之间的桥接结构实现二者的解耦
-
涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类
-
举例:
-
新建 com.pattern.structural.bridge 包,其中新建 Shape 接口
package com.pattern.structural.bridge; public interface Shape { public void draw(String tool); }
-
新建 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"); } }
-
新建 Tools 抽象类
package com.pattern.structural.bridge; public abstract class Tools { public Tools(Shape shape) {} public abstract void use(); }
-
新建 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"); } }
-
新建 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】
-
又称部分整体模式,用于把一组相似的对象当作一个单一的对象
-
依据树形结构来组合对象,用来表示部分以及整体层次
-
创建了一个包含自己对象组的类,该类提供了修改相同对象组的方式
-
举例:一个组织中员工的层次结构
-
新建 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); } }
-
新建 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. 静态代理
-
新建 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 + '\'' + '}'; } }
-
新建 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); }
-
新建 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); } }
-
新建 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("代理对象提交事务"); } }
-
新建 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. 动态代理
-
新建 dynamicproxy 包,其中复制 staticproxy 中的所有类与接口
-
修改 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; } }
-
新建 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】
-
在原有对象不做改变的基础上,将对象的功能附加上
-
提供了比继承更有弹性的替代方案
-
动态地给一个对象添加或撤销功能
-
通过使用不同装饰类以及其排列组合可以实现不同效果
-
举例:煎饼果子
-
新建 com.pattern.structural.decorator 包,其中新建 ABatterCake 抽象类
package com.pattern.structural.decorator; public abstract class ABatterCake { protected abstract String getInfo(); protected abstract int getCost(); }
-
新建 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; } }
-
新建 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(); }
-
新建 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; } }
-
新建 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】
-
提供了减少对象数量从而改善应用所需的对象结构方式
-
运用共享技术有效地支持大量细粒度的对象
-
减少创建对象的数量,从而减少内存的占用,提升性能
-
举例:
-
新建 com.pattern.structural.flyweight 包,其中新建 Employee 接口
package com.pattern.structural.flyweight; public interface Employee { public void report(); }
-
新建 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); } }
-
新建 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; } }
-
新建 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】
-
定义了一个算法的架构,并允许子类为一个或多个步骤的实现
-
模板方法在子类不改变算法结构的情况下,重新定义算法的某些步骤
-
实现一个算法不变的部分,并将可变的控件留给子类来完成
-
子类中公共的行为抽出来并封装到一个公共父类中,提供代码复用性
-
举例:制作课程,不同课程需要笔记情况不同
-
新建 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(); }
-
新建 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"); } }
-
新建 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】
-
提供方法,顺序访问集合对象中的各个元素,同时不暴露对象内部表示
-
为遍历不同的集合结构提供统一的接口,分离了集合对象的遍历行为
-
举例:
-
新建 com.pattern.behavioral.iterator 包,其中新建 Iterator 接口,表示迭代器
package com.pattern.behavioral.iterator; public interface Iterator { public boolean hasNext(); public Object next(); }
-
新建 Container 接口,表示容器
package com.pattern.behavioral.iterator; public interface Container { public Iterator getIterator(); }
-
新建 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; } } }
-
新建 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...
语句的情况可以使用策略模式进行替换 -
提高算法的保密性和安全性
-
举例:两数计算
-
新建 com.pattern.behavioral.strategy 包,其中新建 Strategy 接口
package com.pattern.behavioral.strategy; public interface Strategy { public int operation(int num1, int num2); }
-
新建 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; } }
-
新建 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); } }
-
新建 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】
-
通过给定的语言定义其语法和行为并定义解释器
- 解释器用来解释语言中的句子
-
适用于某个类型问题触发频次高,如处理日志和不同日志格式
-
举例:
-
新建 com.pattern.behavioral.interpreter 包,其中新建 Expression 接口
package com.pattern.behavioral.interpreter; public interface Expression { public boolean interpret(String context); }
-
新建 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); } }
-
新建 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); } }
-
新建 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】
-
当对象之间存在一对多关系时,使用观察者模式,当一个对象被修改时,会自动通知依赖它的对象
-
使多个观察者对象同时监听某一个主题对象,当主题对象发生变化时,它的所有依赖者都会收到通知并更新
-
举例:
-
新建 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(); } } }
-
新建 Observer 抽象类
package com.pattern.behavioral.observer; public abstract class Observer { protected Subject subject; public abstract void update(); }
-
新建 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())); } }
-
新建 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】
-
在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态
-
允许用户取消不确定或错误的操作并恢复到原来的状态
-
举例:
-
新建 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; } }
-
新建 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(); } }
-
新建 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); } }
-
新建 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】
-
将一个请求封装成一个对象,从而可以用不同的请求对客户进行参数化
-
减少行为请求者和行为实现者之间的耦合
-
举例:通过经理人买卖股票
-
新建 com.pattern.behavioral.command 包,其中新建 Order 接口
package com.pattern.behavioral.command; public interface Order { public void execute(); }
-
新建 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."); } }
-
新建 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(); } }
-
新建 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(); } }
-
新建 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】
-
用来降低对多个对象和类之间的通信复杂性
- “调停者”类通常处理不同类之间的通信,并支持松耦合,使代码易于维护
-
对象和对象之间存在大量的关联关系,容易导致系统的结构变得很复杂
-
举例:
-
新建 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); } }
-
新建 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); } }
-
新建 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】
-
为请求创建了一个接收者对象的链,对请求的发送者和接收者进行解耦
-
通常每个接收者都包含对另一个接收者的引用,如果当前接收者不能处理次请求,则会将同一个请求传递到下一个接收者
-
将对象连成链,从而防止请求发送者和接收者耦合在一起
-
举例:
-
新建 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); }
-
新建 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); } }
-
新建 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】
-
元素的执行算法可以随着访问者改变而改变
-
元素对象已接受访问者对象,此时访问者对象就可以处理元素对象上的操作
-
将数据结构与数据操作分离
-
举例:
-
新建 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); }
-
新建 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); } }
-
新建 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); } }
-
新建 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); } }
-
新建 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】
-
类的行为基于其状态进行改变
-
允许对象在内部状态发生改变时改变其行为,对象的行为依赖于其状态
-
举例:
-
新建 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; } }
-
新建 State 接口
package com.pattern.behavioral.state; public interface State { public void operator(Context context); }
-
新建 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..."; } }
-
新建 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-