创建型模式:
单例模式、 工厂模式、抽象工厂模式、建造者模式、原型模式。
结构型模式:
适配器模式,桥接模式,装饰模式,组合模式,外观模式,享元模式,代理模式
行为型模式:
模板方法模式,命令模式,迭代器模式,观察者模式,中介者模式,备忘录模式,解释器模式,状态模式,策略模式,职责链模式, 访问者模式。
单例模式有八种方式:
饿汉式(静态常量)
特点:可以避免线程同步问题,但可能造成内存浪费
public class SingletonTest01 {
public static void main(String[] args) {
// 调用返回都是同个实例对象
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2); // true
}
}
class Singleton{
// 类初始化时就实例化对象
private final static Singleton instance = new Singleton();
// 私有化构造器
private Singleton(){
}
// 提供公有的静态方法给外部调用,返回实例化对象
public static Singleton getInstance(){
return instance;
}
}
public class SingletonTest02 {
public static void main(String[] args) {
// 调用返回都是同个实例对象
Singleton02 instance1 = Singleton02.getInstance();
Singleton02 instance2 = Singleton02.getInstance();
System.out.println(instance1 == instance2);
}
}
class Singleton02{
// 类初始化时就实例化对象
private static Singleton02 instance;
static { // 在静态代码块种实例化对象
instance = new Singleton02();
}
// 私有化构造器
private Singleton02(){
}
// 提供公有的静态方法给外部调用,返回实例化对象
public static Singleton02 getInstance(){
return instance;
}
}
class Singleton03{
private static Singleton03 instance;
private Singleton03(){
}
public static Singleton03 getInstance(){
if (instance == null){ //未创建才创建
instance = new Singleton03();
}
return instance;
}
}
上synchronized锁效率低,不推荐使用
class Singleton04{
private static Singleton04 instance;
private Singleton04(){
}
// 解决线程同步问题
public static synchronized Singleton04 getInstance(){
if (instance == null){ //未创建才创建
instance = new Singleton04();
}
return instance;
}
}
这种方法也不能起到线程同步的作用!!!可能在if判断发生同步问题!
拒绝使用这种方法~!!
class Singleton05{
private static Singleton05 instance;
private Singleton05(){
}
public static Singleton05 getInstance(){
if (instance == null){ //未创建才创建
synchronized (Singleton05.class){
instance = new Singleton05();
}
}
return instance;
}
}
volatile 保证数据的可见性,让线程内存数据的变化立刻显示到主存中,而且有序性可以避免指令重排,但是不保证原子性。
class Singleton06{
private static volatile Singleton06 instance;
private Singleton06(){
}
public static Singleton06 getInstance(){
if (instance == null){ //未创建才创建
synchronized (Singleton06.class){
instance = new Singleton06();
}
}
return instance;
}
}
外部类加载时,静态内部类不会立即加载,静态内部类只加载一次,线程安全。
JVM加载类的时候线程安全。
class Singleton07{
private static Singleton07 instance;
private Singleton07(){
}
private static class SingletonInstance{
private static final Singleton07 INSTANCE = new Singleton07();
}
public static Singleton07 getInstance(){
return SingletonInstance.INSTANCE;
}
}
推荐使用!
public class SingletonTest08 {
public static void main(String[] args) {
// 调用返回都是同个实例对象
Singleton08 instance1 = Singleton08.INSTANCE;
Singleton08 instance2 = Singleton08.INSTANCE;
System.out.println(instance1 == instance2);
}
}
enum Singleton08{
INSTANCE;
}
核心本质:
三种模式:
抽象接口
public interface Car {
void name();
}
各种具体实现类
public class BenChi implements Car {
@Override
public void name() {
System.out.println("奔驰车");
}
}
public class BMW implements Car {
@Override
public void name() {
System.out.println("宝马车");
}
}
工厂类:每次新增具体实现类都得添加代码,破坏了开闭原则
public class CarFactory {
public static Car getCar(String name){
switch (name){
case "奔驰":
return new BenChi();
case "宝马":
return new BMW();
default:
break;
}
return null;
}
}
调用
public class Consumer {
public static void main(String[] args) {
Car car1 = CarFactory.getCar("宝马");
Car car2 = CarFactory.getCar("奔驰");
car1.name();
car2.name();
}
}
每个抽象接口对应的具体实现类都有对应的工厂方法。
抽象接口
public interface Car {
void name();
}
抽象工厂接口
public interface CatFactory {
Car getCar();
}
各种具体实现类和其对应的工厂方法
奔驰车:
public class BenChi implements Car {
@Override
public void name() {
System.out.println("奔驰车");
}
}
public class BenChiFactory implements CatFactory {
@Override
public Car getCar() {
return new BenChi();
}
}
宝马车:
public class BMW implements Car {
@Override
public void name() {
System.out.println("宝马车");
}
}
public class BMWFactory implements CatFactory {
@Override
public Car getCar() {
return new BMW();
}
}
调用
public class Consumer {
public static void main(String[] args) {
Car car1 = new BenChiFactory().getCar();
Car car2 = new BMWFactory().getCar();
car1.name();
car2.name();
}
}
虽说简单工厂模式破坏面向对象的开闭原则,但是实际业务用的多的还是简单工厂模式,因为工厂方法模式的代码复杂不利用管理。
抽象产品族各接口
// 手机 小米手机 ,华为手机为同一产品等级结构
public interface IphoneProduct {
void start();
void shutdown();
}
// 路由器 小米路由器 ,华为路由器为同一产品等级结构
public interface RouterProduct {
void start();
void shutdown();
}
华为系列产品(同个产品族)
// 手机
public class HuaWeiPhone implements IphoneProduct {
@Override
public void start() {
System.out.println("华为手机开启");
}
@Override
public void shutdown() {
System.out.println("华为手机关闭");
}
}
// 路由器
public class HuaWeiRouter implements RouterProduct {
@Override
public void start() {
System.out.println("华为路由器开启");
}
@Override
public void shutdown() {
System.out.println("华为路由器关闭");
}
}
小米系列产品(同个产品族)
// 手机
public class XiaoMIPhone implements IphoneProduct {
@Override
public void start() {
System.out.println("小米手机开启");
}
@Override
public void shutdown() {
System.out.println("小米手机开启");
}
}
// 路由器
public class XiaoMiRouter implements RouterProduct {
@Override
public void start() {
System.out.println("小米路由器开启");
}
@Override
public void shutdown() {
System.out.println("小米路由器关闭");
}
}
抽象产品工厂
// 抽象产品工厂
public interface ProductFactory {
// 生产手机
IphoneProduct iphoneProduct();
// 生产路由器
RouterProduct routerProduct();
}
各个产品族的产品工厂
// 小米工厂
public class XiaoMiFactory implements ProductFactory{
@Override
public IphoneProduct iphoneProduct() {
return new XiaoMIPhone();
}
@Override
public RouterProduct routerProduct() {
return new XiaoRouter();
}
}
// 华为工厂
public class HuaWeiFactory implements ProductFactory{
@Override
public IphoneProduct iphoneProduct() {
return new HuaWeiIPhone();
}
@Override
public RouterProduct routerProduct() {
return new HuaWeiRouter();
}
}
总结:不可以增加产品,但是可以增加产品族。
具体的产品对象
// 具体的产品
public class Product {
private String step1;
private String step2;
private String step3;
public String getStep1() {
return step1;
}
public void setStep1(String step1) {
this.step1 = step1;
}
public String getStep2() {
return step2;
}
public void setStep2(String step2) {
this.step2 = step2;
}
public String getStep3() {
return step3;
}
public void setStep3(String step3) {
this.step3 = step3;
}
@Override
public String toString() {
return "Product{" +
"step1='" + step1 + '\'' +
", step2='" + step2 + '\'' +
", step3='" + step3 + '\'' +
'}';
}
}
设置抽象的建造者
// 抽象的建造者
public abstract class Builder {
abstract void step1();
abstract void step2();
abstract void step3();
// 获得真正的建造产品
abstract Product getProduct();
}
具体的建造者继承抽象的建造者,实现抽象方法
// 具体的建造者
public class Worker extends Builder {
private Product product;
// 创建产品
public Worker(){
product = new Product();
}
@Override
void step1() {
product.setStep1("步骤1");
}
@Override
void step2() {
product.setStep1("步骤2");
}
@Override
void step3() {
product.setStep1("步骤3");
}
@Override
Product getProduct() {
return product;
}
}
核心:指挥者类,负责实例化创建对象,根据传入的具体建造者的对象,创建不同的具体对象,同时可以调整建造方法顺序
// 指挥者:指挥构建工程
public class Director {
public Product build(Builder builder){
// 指挥具体建造者进行对象建造
builder.step1();
builder.step2();
builder.step3();
return builder.getProduct();
}
}
测试
public class Test {
public static void main(String[] args) {
// 先创建一个具体建造者
Worker worker = new Worker();
// 创建一个指挥者,指挥具体建造者
Director director = new Director();
director.build(worker);
}
}
进一步优化,去掉指挥者,使用静态内部类,修改抽象建造者类,且具体产品赋予默认值
// 具体的产品
public class Product {
private String step1 = "步骤1";
private String step2 = "步骤2";
private String step3 = "步骤3";
public String getStep1() {
return step1;
}
public void setStep1(String step1) {
this.step1 = step1;
}
public String getStep2() {
return step2;
}
public void setStep2(String step2) {
this.step2 = step2;
}
public String getStep3() {
return step3;
}
public void setStep3(String step3) {
this.step3 = step3;
}
@Override
public String toString() {
return "Product{" +
"step1='" + step1 + '\'' +
", step2='" + step2 + '\'' +
", step3='" + step3 + '\'' +
'}';
}
}
// 抽象的建造者
public abstract class Builder {
abstract Builder step1(String msg);
abstract Builder step2(String msg);
abstract Builder step3(String msg);
// 获得真正的建造产品
abstract Product getProduct();
}
// 具体的建造者
public class Worker extends Builder {
private Product product;
// 创建产品
public Worker(){
product = new Product();
}
@Override
Builder step1(String msg) {
product.setStep1(msg);
return this;
}
@Override
Builder step2(String msg) {
product.setStep1(msg);
return this;
}
@Override
Builder step3(String msg) {
product.setStep1(msg);
return this;
}
@Override
Product getProduct(String msg) {
return product;
}
}
测试
public class Test {
public static void main(String[] args) {
// 创建一个具体建造者
Worker worker = new Worker();
Product product = Worker.getProduct(); // 使用设置的默认值
Product product = Worker.step1("步骤1").step2("步骤2").getProduct(); // 可以改变方法顺序,同时可以修改默认值
}
}
总结:
使用Object的clone方法进行克隆,bean对象实现Cloneable接口,实现父类的clone()方法,里面有方法引用的需要进行属性克隆。
定义:将一个类的接口转换成客户希望的另外-一个接口。 Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作!
角色分析:
想要调用的目标类
public class Adaptee {
public void connect(){
System.out.println("连接");
}
}
适配器接口
// 接口转换器的抽象接口
public interface NetToUsb {
// 处理转换
public void handleRequest();
}
适配器实现类
// 真正的适配器
// 1. 继承(类适配器,单一继承)
//public class Adapter extends Adaptee implements NetToUsb{
//
// @Override
// public void handleRequest() {
// super.connect();
// }
//}
// 2. 组合(对象适配器,多适配)
public class Adapter implements NetToUsb{
private Adaptee adaptee;
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void handleRequest() {
adaptee.connect();
}
}
需要适配的类
public class Computer {
public void internet(NetToUsb adapter){
adapter.handleRequest();
}
}
测试
public static void main(String[] args) {
Computer computer = new Computer(); // 需要适配的类
Adaptee adaptee = new Adaptee(); // 适配的对象类
Adapter adapter = new Adapter(adaptee); // 适配器类
computer.internet(adapter); // 调用适配对象的方法
}
对象适配器优点:
类适配器缺点:
应用场景:
品牌抽象接口
// 品牌
public interface Brand {
void info();
}
各具体品牌类
public class Apple implements Brand {
@Override
public void info() {
System.out.println("苹果");
}
}
public class Lenvo implements Brand {
@Override
public void info() {
System.out.println("联想");
}
}
抽象的电脑类型类
// 抽象的电脑类型类
public abstract class Computer {
protected Brand brand;
public Computer(Brand brand) {
this.brand = brand;
}
public void info(){
brand.info();
}
}
具体的电脑类型实现类
class Desktop extends Computer{
public Desktop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("台式机");
}
}
class Laptop extends Computer{
public Laptop(Brand brand) {
super(brand);
}
@Override
public void info() {
super.info();
System.out.println("笔记本");
}
}
测试组装起来
public class Test {
public static void main(String[] args) {
// 苹果笔记本
Computer computer1 = new Laptop(new Apple());
computer1.info();
// 联想台式机
Computer computer2 = new Desktop(new Lenvo());
computer2.info();
}
}
好处分析:
桥接模式偶尔类似于多继承方案,但是多继承方案违背了类的单一职责原则,复用性比较差,类的个数也非常多,桥接模式是比多继承方案更好的解决方法。极大的减少了子类的个数,从而降低管理和维护的成本
桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度, 都不需要修改原
有系统。符合开闭原则,就像- -座桥,可以把两个变化的维度连接起来!
劣势分析:
使用的场景:
总结:如果一个类存在两个独立变化的维度,且这两个维度都需要进行扩展,或者不希望使用继承或者多层级继承导致类数量变多的系统,就可使用桥接模式。特别可以让程序同时适用Linux,window等系统时可以使用该模式。
装饰者模式: 动态的将新功能附加到对象上。在对象功能扩展方面,它比继承更有弹性,装饰者模式也体现了开闭原则(ocp)
public class Test {
public static void main(String[] args) {
DataInputStream dis = new DataInputStream(new FileInputStream("c:\\abc.txt"));
System.out.println(dis.read());
dis. close();
}
}
IO流中的InputStream 是抽象类,为被装饰者,
FileInputStream 是 InputStream的子类,
FilterInputStream 是 InputStream 子类,作为修饰者,
DataInputStream 是 FilterInputStream子类,作为具体的修饰者
FilterInputStream类有 protected volatile InputStream in; 即含被装饰者
基本介绍:
解决问题的类型:组合模式解决当我们的要处理的对象可以生成一颗树形结构,而我们要对树上的节点和叶子进行操作时,它能够提供-致的方式,而不用考虑它是节点还是叶子。
抽象类
public abstract class OrganizationComponent {
private String name;
private String des;
public OrganizationComponent(String name, String des) {
this.name = name;
this.des = des;
}
protected void add(OrganizationComponent organizationComponent){
// 默认不能操作
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent){
// 默认不能操作
throw new UnsupportedOperationException();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
// 子类都需实现
protected abstract void print();
}
大学类
public class University extends OrganizationComponent{
List<OrganizationComponent> organizationComponents = new ArrayList<>();
public University(String name, String des) {
super(name, des);
}
@Override
protected void add(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
@Override
protected void print() {
System.out.println(getName());
for (OrganizationComponent organizationComponent:organizationComponents){
organizationComponent.print();
}
}
}
学院类
public class College extends OrganizationComponent{
// List 存放department
List<OrganizationComponent> organizationComponents = new ArrayList<>();
public College(String name, String des) {
super(name, des);
}
@Override
protected void add(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void remove(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
@Override
protected void print() {
System.out.println(getName());
for (OrganizationComponent organizationComponent:organizationComponents){
organizationComponent.print();
}
}
}
最底层的叶子节点类–>系
public class Department extends OrganizationComponent {
public Department(String name, String des) {
super(name, des);
}
@Override
protected void print() {
System.out.println(getName());
}
}
测试
public class Client {
public static void main(String[] args) {
// 从高到低
// 大学
OrganizationComponent university = new University("北京大学", "666");
// 学院
OrganizationComponent college1 = new College("计算机学院", "999");
OrganizationComponent college2 = new College("金融学院", "555");
// 系
college1.add(new Department("软件工程", "666"));
college1.add(new Department("网格工程", "666"));
college2.add(new Department("国贸专业", "999"));
college2.add(new Department("商贸专业", "999"));
// 学院加入到大学中
university.add(college1);
university.add(college2);
university.print();
college1.print();
}
}
基本介绍:
基本关系:
子系统类TV
public class TV {
private final static TV instance = new TV();
private TV() {
}
public static TV getInstance(){
return instance;
}
public void on(){
System.out.println("电视开启");
}
public void off(){
System.out.println("电视关闭");
}
}
子系统Player
public class Player {
private final static Player instance = new Player();
private Player() {
}
public static Player getInstance(){
return instance;
}
public void on(){
System.out.println("音乐开启");
}
public void off(){
System.out.println("音乐关闭");
}
}
外观模式管理器类
public class Facade {
private TV tv;
private Player player;
public Facade() {
this.tv = TV.getInstance();
this.player = Player.getInstance();
}
// 全部开启
public void ready(){
tv.on();
player.on();
}
// 全部关闭
public void end(){
player.off();
tv.off();
}
}
测试
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.ready();
facade.end();
}
}
基本介绍:
网站抽象类
public abstract class WebSite {
public abstract void use(User user);
}
具体实现类(可共享的内部状态)
public class ConcreteWebSite extends WebSite{
// 内部状态 可以共享
private String type = "";// 网站类型
public ConcreteWebSite(String type) {
this.type = type;
}
@Override
public void use(User user) {
System.out.println("网站的发布形式为:"+type+",使用的用户是:"+user.getName());
}
}
用户对象为外部状态不可共享
// 作为外部状态,不能共享
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
享元工厂类
// 网站工厂类
public class WebSiteFactory {
// 池集合
private HashMap<String,ConcreteWebSite> pool = new HashMap<>();
// 根据类型返回一个网站,如果没有该类型就创建一个网站,并放入池集合进行管理
public WebSite getWebSite(String type){
if (!pool.containsKey(type)){
pool.put(type,new ConcreteWebSite(type));
}
return pool.get(type);
}
// 获取池集合中有多个类型的网站
public int getWebSiteNum(){
return pool.size();
}
}
测试
public class Client {
public static void main(String[] args) {
WebSiteFactory webSiteFactory = new WebSiteFactory();
WebSite webSite1 = webSiteFactory.getWebSite("新闻");
webSite1.use(new User("111"));
WebSite webSite2 = webSiteFactory.getWebSite("博客");
webSite2.use(new User("222"));
WebSite webSite3 = webSiteFactory.getWebSite("博客");
webSite3.use(new User("333"));
System.out.println("网站的实际类型数量:"+webSiteFactory.getWebSiteNum());
}
}
附加例子:jdk中的Integer的valueof产生的对象, 数值如果是-128~127之间的对象是相同的,缓存池的作用。
基本介绍:
角色分析:
抽象角色类
public interface ITeacherDao {
void teach();
}
真实角色类
public class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("授课中~");
}
}
代理角色类
// 代理类
public class TeacherProxy implements ITeacherDao {
// 目标类
private ITeacherDao teacherDao;
public TeacherProxy(ITeacherDao teacherDao) {
this.teacherDao = teacherDao;
}
@Override
public void teach() {
System.out.println("代理中~");
teacherDao.teach();
}
}
客户类
public class Client {
public static void main(String[] args) {
TeacherDao teacherDao = new TeacherDao();
TeacherProxy teacherProxy = new TeacherProxy(teacherDao);
teacherProxy.teach();
}
}
优点:
缺点:
基本介绍:
抽象角色类
public interface ITeacherDao {
void teach();
void write(String msg);
}
真实角色类
public class TeacherDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("授课中~");
}
@Override
public void write(String msg) {
System.out.println("写了"+msg);
}
}
代理角色类
// 代理类
public class TeacherProxy implements ITeacherDao {
// 目标类
private Object target;
public TeacherProxy(ITeacherDao target) {
this.target = target;
}
public Object getProxyInstance() {
// loader:指定当前目标对象使用的类加载器,获取加载器的方法固定
// interfaces:目标对象实现的接口类型,使用泛型确认类型
// InvocationHandler: 事件处理,执行目标对象的方法时,会触发事件处理器方法,会把当前执行对象的方法作为参数传入
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理开始");
Object result = method.invoke(target, args);
System.out.println("代理结束");
return result;
}
});
}
}
客户类
public class Client {
public static void main(String[] args) {
// 创建目标对象
ITeacherDao teacherDao = new TeacherDao();
// 给目标对象创建代理对象,转成接口
ITeacherDao teacherProxy = (ITeacherDao) new TeacherProxy(teacherDao).getProxyInstance();
// 调用目标对象的方法
teacherProxy.teach();
teacherProxy.write("测试");
}
}
与动态代理的区别,目标对象不用实现任何接口,需要导入Cglib的相关jar包才能实现。
目标对象类
public class TeacherDao{
public void teach() {
System.out.println("授课中~");
}
}
代理类
// 代理类
public class TeacherProxy implements MethodInterceptor {
// 目标类
private Object target;
public TeacherProxy(ITeacherDao target) {
this.target = target;
}
// 为目标对象的代理对象
public Object getProxyInstance() {
//1.创建一个工具类
Enhancer enhancer = new Enhancer();
//2.设置父类
enhancer.setSuperclass(target.getClass());
//3.设置回调函数
enhancer.setCallback(this);
//4.创建子类对象,即代理对象
return enhancer.create();
}
//重写intercept方法,会调用目标对象的方法
@Override
public 0bject intercept(object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("代理开始");
Object result = method.invoke(target,arg2);
System.out.println("代理结束");
return result;
}
}
客户类测试
public class Client {
public static void main(String[] args) {
// 创建目标对象
TeacherDao target = new TeacherDao();
// 给目标对象创建代理对象,转成接口
TeacherDao teacherProxy = (ITeacherDao) new TeacherProxy(target).getProxyInstance();
// 执行代理对象的方法,触发拦截器方法,从而调用目标对象的方法
teacherProxy.teach();
}
}
抽象模板类
public abstract class SoyaMilk {
// 模板方法
final void make(){
select();
if (isAddOther()) {
addOther();
}
cook();
}
void select(){
System.out.println("选材");
}
abstract void addOther();
void cook(){
System.out.println("烹煮");
}
// 钩子方法,默认添加
boolean isAddOther(){
return true;
};
}
各种具体类
public class PeanutSoya extends SoyaMilk {
@Override
void addOther() {
System.out.println("加入花生");
}
}
public class RedSoya extends SoyaMilk {
@Override
void addOther() {
System.out.println("加入红豆");
}
}
public class PureSoya extends SoyaMilk {
// 表示不添加别的东西
@Override
boolean isAddOther(){
return false;
};
}
测试调用
public class Client {
public static void main(String[] args) {
// 制作红豆豆浆
SoyaMilk redSoya = new RedSoya();
redSoya.make();
// 制作花生豆浆
SoyaMilk peanutSoya = new PeanutSoya();
peanutSoya.make();
}
}
基本介绍:
抽象命令类
public interface Command {
public void execute();
public void undo();
}
电灯对象(命令接收者)
public class LightReceiver {
public void on(){
System.out.println("开启");
}
public void off(){
System.out.println("关闭");
}
}
电灯开的类
public class LightOnCommand implements Command {
private LightReceiver lightReceiver;
public LightOnCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.on();
}
@Override
public void undo() {
lightReceiver.off();
}
}
电灯关的类
public class LightOffCommand implements Command{
private LightReceiver lightReceiver;
public LightOffCommand(LightReceiver lightReceiver) {
this.lightReceiver = lightReceiver;
}
@Override
public void execute() {
lightReceiver.off();
}
@Override
public void undo() {
lightReceiver.on();
}
}
空命令,防止无效命令
// 空命令,不执行任何操作
public class NoCommand implements Command{
@Override
public void execute() {
}
@Override
public void undo() {
}
}
控制器(命令发送者)
public class RemoteController {
Command[] onCommandArr;
Command[] offCommandArr;
// 撤销命令
Command undoCommand;
// 初始化命令
public RemoteController(){
undoCommand = new NoCommand();
onCommandArr = new Command[5];
offCommandArr = new Command[5];
for (int i =0 ;i<5;i++){
onCommandArr[i] = new NoCommand();
offCommandArr[i] = new NoCommand();
}
}
public void setCommand(int num,Command onCommand,Command offCommand){
onCommandArr[num] = onCommand;
offCommandArr[num] = offCommand;
}
// 按下开
public void onOpen(int num){
onCommandArr[num].execute();
// 同时记录操作
undoCommand = onCommandArr[num];
}
// 按下关
public void offEnd(int num){
offCommandArr[num].execute();
// 同时记录操作
undoCommand = offCommandArr[num];
}
// 按下撤销操作
public void unDoCommand(){
undoCommand.undo();
}
}
用户测试类
public class Client {
public static void main(String[] args) {
// 电灯对象
LightReceiver lightReceiver = new LightReceiver();
// 电灯开和关对象
LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
LightOffCommand lightOffCommand = new LightOffCommand(lightReceiver);
// 创建一个控制对象
RemoteController remoteController = new RemoteController();
// 给控制对象设置命令
remoteController.setCommand(0, lightOnCommand,lightOffCommand);
remoteController.onOpen(0); // 开
remoteController.offEnd(0); // 关
remoteController.unDoCommand(); // 撤销上一步操作
}
}
注意点:
基本介绍:
访问动作抽象类
public abstract class action {
public abstract void getManResult(Man man);
public abstract void getWomanResult(Woman woman);
}
动作具体实现类
public class Success extends action {
@Override
public void getManResult(Man man) {
System.out.println("男成功");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女成功");
}
}
public class Fail extends action {
@Override
public void getManResult(Man man) {
System.out.println("男失败");
}
@Override
public void getWomanResult(Woman woman) {
System.out.println("女失败");
}
}
被访问者抽象类
public abstract class Person {
public abstract void accept(action action);
}
被访问者具体实现类
public class Man extends Person {
@Override
public void accept(action action) {
action.getManResult(this);
}
}
public class Woman extends Person {
@Override
public void accept(action action) {
action.getWomanResult(this);
}
}
管理者类
public class ObjectStructure {
private List<Person> persons = new LinkedList<>();
public void attach(Person person){
persons.add(person);
}
public void detach(Person person){
persons.remove(person);
}
public void display(action action){
for (Person p:persons){
p.accept(action);
}
}
}
测试类
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.attach(new Man());
objectStructure.attach(new Woman());
Success success = new Success();
objectStructure.display(success);
}
}
优点:
缺点:
基本介绍:
学院抽象类
public interface College {
public String getName();
public void addDepartment(String name,String des);
public Iterator createIterator();
}
学院具体实现类
public class CpCollege implements College {
Department[] departments;
int num = 0;
public CpCollege() {
departments = new Department[5];
addDepartment("软件工程", "666");
addDepartment("网络工程", "666");
}
@Override
public String getName() {
return "计算机学院";
}
@Override
public void addDepartment(String name,String des) {
Department department = new Department(name, des);
departments[num] = department;
num++;
}
@Override
public Iterator createIterator() {
return new CpCollegeIterator(departments);
}
}
自定义的学院迭代器
public class CpCollegeIterator implements Iterator {
Department[] departments;
int pos = 0;
public CpCollegeIterator(Department[] departments) {
this.departments = departments;
}
@Override
public boolean hasNext() {
if (pos>=departments.length|| departments[pos]==null){
return false;
}
return true;
}
@Override
public Object next() {
Department department = departments[pos];
pos++;
return department;
}
@Override
public void remove() {
}
}
迭代输出类
public class OutPutImpl {
List<College> collegeList;
public OutPutImpl(List<College> collegeList) {
this.collegeList = collegeList;
}
public void printCollege(){
Iterator<College> iterator = collegeList.iterator();
while (iterator.hasNext()){
College college = iterator.next();
System.out.println(college.getName());
printDepartment(college.createIterator());
}
}
public void printDepartment(Iterator iterator){
while (iterator.hasNext()){
Department d = (Department) iterator.next();
System.out.println(d.getName());
}
}
}
测试
public class Client {
public static void main(String[] args) {
ArrayList<College> colleges = new ArrayList<>();
CpCollege cpCollege = new CpCollege();
colleges.add(cpCollege);
OutPutImpl outPut = new OutPutImpl(colleges);
outPut.printCollege();
}
}
优点:
提供一个统一的方法遍历对象,客户不用再考虑聚合的类型,使用一种方法就可以
遍历对象了。
隐藏了聚合的内部结构,客户端要遍历聚合的时候只能取到迭代器,而不会知道聚
合的具体组成。
提供了一种设计思想,就是一个类应该只有一个引起变化的原因(叫做单一责任
原则)。在聚合类中,我们把迭代器分开,就是要把管理对象集合和遍历对象集
合的责任分开,这样-来集合改变的话,只影响到聚合对象。而如果遍历方式改变
的话,只影响到了迭代器。
当要展示一组相似对象,或者遍历一组相同对象时使用,适合使用迭代器模式
缺点:
观察者模式: 对象之间多对一-依赖的一 种设计方案,被依赖的对象为Subject,依赖的对象为Observer, Subject通知Observer变化。
优点:
Subject类:首先定义一个观察者数组,并实现增、删及通知操作。它的职责很简单,就是定义谁能观察,谁不能观察,用Vector是线程同步的,比较安全,也可以使用ArrayList,是线程异步的,但不安全。
public class Subject {
//观察者数组
private Vector<Observer> vector = new Vector<>();
//增加一个观察者
public void addObserver(Observer observer) {
vector.add(observer);
}
//删除一个观察者
public void deleteObserver(Observer observer) {
vector.remove(observer);
}
//通知所有观察者
public void notifyObserver() {
for(Observer observer : vector) {
observer.update();
}
}
}
抽象观察者Observer类:观察者一般是一个接口,每一个实现该接口的实现类都是具体观察者。
public interface Observer {
//更新数据
public void update();
}
具体主题子类:继承Subject类,在这里实现具体业务,在具体项目中,该类会有很多变种。
public class ConcreteSubject extends Subject {
//具体业务操作
public void doSomething() {
//相关操作。。。
super.notifyObserver();
}
}
具体观察者:实现Observer接口。
public class ConcreteObserver implements Observer {
@Override
public void update() {
// 接受主题的消息。
}
}
客户端测试类
public class Client {
public static void main(String[] args) {
//创建一个主题
ConcreteSubject subject = new ConcreteSubject();
//定义一个观察者
Observer observer = new ConcreteObserver();
//将观察者添加到主题中
subject.addObserver(observer);
//开始活动
subject.doSomething();
}
}
基本介绍:
Mediator 就是抽象中介者,定义了同事对象到中介者对象的接口
Colleague 是抽象同事类
ConcreteMediator 具体的中介者对象, 实现抽象方法, 他需要知道所有的具体的同事类,即以一个集合来管理HashMap,并接受某个同事对象消息,完成相应的任务
ConcreteColleague 具体的同事类,会有很多, 每个同事只知道自己的行为, 而不了解其他同事类的行为(方法), 但 是他们都依赖中介者对象
抽象同事类
public abstract class Colleague {
private Mediator mediator;
public String name;
public Colleague(Mediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}
public Mediator GetMediator() {
return this.mediator;
}
public abstract void SendMessage(int stateChange);
}
具体同事类
public class Alarm extends Colleague {
//构造器
public Alarm(Mediator mediator, String name) {
super(mediator, name);
//在创建 Alarm 同事对象时,将自己放入到 ConcreteMediator 对象中[集合]
mediator.Register(name, this);
}
public void SendAlarm(int stateChange) {
SendMessage(stateChange);
}
@Override
public void SendMessage(int stateChange) {
// 调 用 的 中 介 者 对 象 的 getMessage
this.GetMediator().GetMessage(stateChange, this.name);
}
}
抽象中介类
public abstract class Mediator {
//将给中介者对象,加入到集合中
public abstract void Register(String colleagueName, Colleague colleague);
//接收消息, 具体的同事对象发出
public abstract void GetMessage(int stateChange, String colleagueName);
public abstract void SendMessage();
}
具体的中介者类
public class ConcreteMediator extends Mediator {
//集合,放入所有的同事对象
private HashMap<String, Colleague> colleagueMap;
private HashMap<String, String> interMap;
public ConcreteMediator() {
colleagueMap = new HashMap<String, Colleague>();
interMap = new HashMap<String, String>();
}
@Override
public void Register(String colleagueName, Colleague colleague) {
colleagueMap.put(colleagueName, colleague);
if (colleague instanceof Alarm) {
interMap.put("Alarm", colleagueName);
}else if(..){
...
}
}
//1. 根据得到消息,完成对应任务
//2. 中介者在这个方法,协调各个具体的同事对象,完成任务
@Override
public void GetMessage(int stateChange, String colleagueName) {
//处理闹钟发出的消息
if (colleagueMap.get(colleagueName) instanceof Alarm) {
.....
} else if (colleagueMap.get(colleagueName) instanceof Curtains) {
//如果是以窗帘发出的消息,这里处理...
}
}
@Override
public void SendMessage() {
}
}
优点:
缺点:
基本介绍:
人物初始值类
public class Originator {
private String state; // 状态
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
// 返回一个状态对象
public Memento SaveMemento(){
return new Memento(state);
}
//通过备忘录对象,恢复状态
public void getStateFromMemento(Memento memento) {
state = memento.getState();
}
}
状态类
public class Memento {
private String state;
public Memento(String state) {
this.state = state;
}
public String getState() {
return state;
}
}
备忘录对象类
public class Caretaker {
private List<Memento> mementoList = new ArrayList<>();
public void add(Memento memento){
mementoList.add(memento);
}
public Memento get(int index){
return mementoList.get(index);
}
}
测试
public class Client {
public static void main(String[] args) {
Originator originator = new Originator();
Caretaker caretaker = new Caretaker();
originator.setState("1");
// 保存当前状态1
caretaker.add(originator.SaveMemento());
originator.setState("2");
// 保存当前状态2
caretaker.add(originator.SaveMemento());
// 从状态2恢复到状态1
System.out.println("当前状态:"+originator.getState());
//originator.setState(caretaker.get(0).getState());
originator.getStateFromMemento(caretaker.get(0));
System.out.println("恢复状态:"+originator.getState());
}
}
注意点:
给用户提供了一种可以恢复状态的机制,可以使用户能够比较方便地回到某个历史的状态。
实现了信息的封装,使得用户不需要关心状态的保存细节。
如果类的成员变量过多,势必会占用比较大的资源,而且每一次保存都会消耗一定的内存, 这个需要注意。
适用的应用场景:
1、后悔药。
2、打游戏时的存档。
3、Windows 里的 ctri + z。
4、IE 中的后退。
5、数据库的事务管理
基本介绍:
在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器
解释器模式(Interpreter Pattern):是指给定一个语言**(表达式),定义它的文法的一种表示,并定义一个解释器, 使用该解释器来解释语言中的句子(**表达式)
应用场景
应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
一些重复出现的问题可以用一种简单的语言来表达
一个简单语法需要解释的场景
这样的例子还有,比如编译器、运算表达式计算、正则表达式、机器人等
Context: 是环境角色,含有解释器之外的全局信息.
AbstractExpression: 抽象表达式, 声明一个抽象的解释操作,这个方法为抽象语法树中所有的节点所共享
TerminalExpression: 为终结符表达式, 实现与文法中的终结符相关的解释操作
NonTermialExpression: 为非终结符表达式,为文法中的非终结符实现解释操作.
说明: 输入 Context he TerminalExpression 信息通过 Client 输入即可
解释器封装类
public class Calculator {
//定义表达式
private Expression expression;
//构造函数传参,并解析
public Calculator(String expStr) {
//安排运算先后顺序
Stack<Expression> stack = new Stack<>();
//表达式拆分为字符数组
char[] charArray = expStr.toCharArray();
Expression left = null;
Expression right = null;
for(int i=0; i<charArray.length; i++) {
switch (charArray[i]) {
case '+': //加法
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new AddExpression(left, right));
break;
case '-': //减法
left = stack.pop();
right = new VarExpression(String.valueOf(charArray[++i]));
stack.push(new SubExpression(left, right));
break;
default: //公式中的变量
stack.push(new VarExpression(String.valueOf(charArray[i])));
break;
}
}
this.expression = stack.pop();
}
//计算
public int run(HashMap<String, Integer> var) {
return this.expression.interpreter(var);
}
}
抽象表达式类
public abstract class Expression {
//解析公式和数值,key是公式中的参数,value是具体的数值
public abstract int interpreter(HashMap<String, Integer> var);
}
变量解析器
public class VarExpression extends Expression {
private String key;
public VarExpression(String key) {
this.key = key;
}
// var 为存的变量与值的键值对
@Override
public int interpreter(HashMap<String, Integer> var) {
return var.get(this.key);
}
}
运算符号解析器
public class SymbolExpression extends Expression {
protected Expression left;
protected Expression right;
public SymbolExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
// 由子类实现
@Override
public int interpreter(HashMap<String, Integer> var) {
// TODO Auto-generated method stub
return 0;
}
}
加法解析器
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
public int interpreter(HashMap<String, Integer> var) {
return super.left.interpreter(var) + super.right.interpreter(var);
}
}
减法解析器
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
public int interpreter(HashMap<String, Integer> var) {
return super.left.interpreter(var) - super.right.interpreter(var);
}
}
测试
public class Client {
public static void main(String[] args) throws IOException {
String expStr = getExpStr();
HashMap<String, Integer> var = getValue(expStr);
Calculator calculator = new Calculator(expStr);
System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
}
//获得表达式
public static String getExpStr() throws IOException {
System.out.print("请输入表达式:");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}
//获得值映射
public static HashMap<String, Integer> getValue(String expStr) throws IOException {
HashMap<String, Integer> map = new HashMap<>();
for(char ch : expStr.toCharArray()) {
if(ch != '+' && ch != '-' ) {
if(! map.containsKey(String.valueOf(ch))) {
System.out.print("请输入" + String.valueOf(ch) + "的值:");
String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
map.put(String.valueOf(ch), Integer.valueOf(in));
}
}
}
return map;
}
}
基本介绍:
Context 类为环境角色, 用于维护 State 实例,这个实例定义当前状态
State 是抽象状态角色,定义一个接口封装与 Context 的一个特点接口相关行为
ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为
Context类
环境角色具有两个职责,即处理本状态必须完成的任务,及决定是否可以过渡到其它状态。对于环境角色,有几个不成文的约束:
public class Context {
//定义状态
public final static State STATE1 = new ConcreteState1();
public final static State STATE2 = new ConcreteState2();
//当前状态
private State currentState;
//获得当前状态
public State getCurrentState() {
return currentState;
}
//设置当前状态
public void setCurrentState(State currentState) {
this.currentState = currentState;
//切换状态
this.currentState.setContext(this);
}
public void handle1() {
this.currentState.handle1();
}
public void handle2() {
this.currentState.handle2();
}
}
State抽象类
抽象环境中声明一个环境角色,提供各个状态类自行访问,并且提供所有状态的抽象行为,由各个实现类实现。
public abstract class State {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
//行为1
public abstract void handle1();
//行为2
public abstract void handle2();
}
具体状态
public class ConcreteState1 extends State {
@Override
public void handle1() {
//...
System.out.println("ConcreteState1 的 handle1 方法");
}
@Override
public void handle2() {
super.context.setCurrentState(Context.STATE2);
System.out.println("ConcreteState1 的 handle2 方法");
}
}
public class ConcreteState2 extends State {
@Override
public void handle1() {
//...
System.out.println("ConcreteState2 的 handle1 方法");
}
@Override
public void handle2() {
super.context.setCurrentState(Context.STATE2);
System.out.println("ConcreteState2 的 handle2 方法");
}
}
测试
public class Client {
public static void main(String[] args) {
//定义环境角色
Context context = new Context();
//初始化状态
context.setCurrentState(new ConcreteState1());
//行为执行
context.handle1();
context.handle2();
}
}
注意细节:
代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中。
方便维护。将容易产生问题的 if-else 语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产出很多 if-else 语句,而且容易出错。
符合“开闭原则”。容易增删状态。
会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度。
应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候, 可以考虑使用状态模式。
基本介绍:
Context:上下文角色,也叫Context封装角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。
Strategy :抽象策略角色,是对策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性
ConcreteStrategy:用于实现抽象策略中的操作,即实现具体的算法,不同策略不同类。
Context类(上下文角色)
public class Context {
Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
//上下文接口
public void contextInterface() {
strategy.algorithmInterface();
}
}
Strategy抽象类(策略角色)
public abstract class Strategy {
//算法方法
public abstract void algorithmInterface();
}
具体策略角色
public class ConcreteStrategyA extends Strategy {
@Override
public void algorithmInterface() {
System.out.println("算法A实现");
}
}
public class ConcreteStrategyB extends Strategy {
@Override
public void algorithmInterface() {
System.out.println("算法B实现");
}
}
测试
public class Client {
public static void main(String[] args) {
Context context;
// 设置策略
context = new Context(new ConcreteStrategyA());
context.contextInterface();
// 设置修改策略
context = new Context(new ConcreteStrategyB());
context.contextInterface();
}
}
策略模式的应用:
抽象鸭子类
public abstract class Duck {
//属性, 策略接口
FlyBehavior flyBehavior;
public Duck() {
}
public abstract void display();//显示鸭子信息
public void quack() {
System.out.println("鸭子嘎嘎叫~~");
}
public void swim() {
System.out.println("鸭子会游泳~~");
}
public void fly() {
//改进
if(flyBehavior != null) {
flyBehavior.fly();
}
}
public void setFlyBehavior(FlyBehavior flyBehavior) {
this.flyBehavior = flyBehavior;
}
}
飞的接口
public interface FlyBehavior {
void fly(); // 子类具体实现
}
实现会飞的接口行为
public class GoodFlyBehavior implements FlyBehavior {
@Override
public void fly() {
System.out.println("会飞");
}
}
实现不会飞的接口行为
public class NoFlyBehavior implements FlyBehavior{
@Override
public void fly() {
System.out.println("不会飞翔");
}
}
实现的鸭子类(会飞)
public class PekingDuck extends Duck {
//假如北京鸭会飞。
public PekingDuck() {
flyBehavior = new GoodFlyBehavior();
}
@Override
public void display() {
System.out.println("~~北京鸭~~~");
}
}
实现的鸭子类(玩具鸭,不会飞,不会游泳)
public class ToyDuck extends Duck{
public ToyDuck() {
flyBehavior = new NoFlyBehavior();
}
@Override
public void display() {
System.out.println("玩具鸭");
}
//需要重写父类的所有方法
public void quack() {
System.out.println("玩具鸭不能叫~~");
}
public void swim() {
System.out.println("玩具鸭不会游泳~~");
}
}
客户端测试
public class Client {
public static void main(String[] args) {
ToyDuck toyDuck = new ToyDuck();
toyDuck.fly();
PekingDuck pekingDuck = new PekingDuck();
pekingDuck.fly();
//动态改变某个对象的行为, 北京鸭 不能飞
pekingDuck.setFlyBehavior(new NoFlyBehavior());
System.out.println("北京鸭的实际飞翔能力");
pekingDuck.fly();
}
}
注意细节:
策略模式的关键是:分析项目中变化部分与不变部分
策略模式的核心思想是:多用组合/聚合 少用继承;用行为类组合,而不是行为的继承。更有弹性
体现了“对修改关闭,对扩展开放”原则,客户端增加行为不用修改原有代码,只要添加一种策略(或者行为) 即可,避免了使用多重转移语句(if…else if…else)
提供了可以替换继承关系的办法: 策略模式将算法封装在独立的 Strategy 类中使得你可以独立于其 Context 改变它,使它易于切换、易于理解、易于扩展
需要注意的是:每添加一个策略就要增加一个类,当策略过多是会导致类数目庞
基本介绍:
类图
Handler : 抽象的处理者, 定义了一个处理请求的接口, 同时含义另外 Handler
ConcreteHandlerA , B 是具体的处理者, 处理它自己负责的请求, 可以访问它的后继者(即下一个处理者), 如果可以处理当前请求,则处理,否则就将该请求交个 后继者去处理,从而形成一个职责链
Request , 含义很多属性,表示一个请求
具体例子:
客户请求类
// 客户请求类
public class PurchaseRequest {
private int type = 0; // 类型
private float price = 0.0f; // 价格
private int id = 0; // id
public PurchaseRequest(int type, float price, int id) {
this.type = type;
this.price = price;
this.id = id;
}
public int getType() {
return type;
}
public float getPrice() {
return price;
}
public int getId() {
return id;
}
}
抽象处理者
public abstract class Approver {
Approver approver; // 下一个处理者
String name;
public Approver(String name) {
this.name = name;
}
// 设置下一个处理的人
public void setApprover(Approver approver) {
this.approver = approver;
}
// 处理请求的方法,由子类完成
public abstract void processRequest(PurchaseRequest purchaseRequest);
}
具体处理者
// 系处理
public class DepartmentApprover extends Approver {
public DepartmentApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice()<=500){
System.out.println("请求id:"+purchaseRequest.getId()+",本次请求由系【"+this.name+"】处理了");
}else{
// 不行就由下一个处理者处理
this.approver.processRequest(purchaseRequest);
}
}
}
// 院处理
public class CollegeApprover extends Approver {
public CollegeApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice()>500 && purchaseRequest.getPrice()<=1000){
System.out.println("请求id:"+purchaseRequest.getId()+",本次请求由院【"+this.name+"】处理了");
}else{
// 不行就由下一个处理者处理
this.approver.processRequest(purchaseRequest);
}
}
}
// 校处理
public class SchoolApprover extends Approver {
public SchoolApprover(String name) {
super(name);
}
@Override
public void processRequest(PurchaseRequest purchaseRequest) {
if (purchaseRequest.getPrice()>1000){
System.out.println("请求id:"+purchaseRequest.getId()+",本次请求由校【"+this.name+"】处理了");
}else{
// 最后不能处理就报错
throw new UnsupportedOperationException("无法处理该请求!");
}
}
}
测试
public class Client {
public static void main(String[] args) {
PurchaseRequest purchaseRequest = new PurchaseRequest(1,1200,0);
// 创建各个处理者
DepartmentApprover departmentApprover = new DepartmentApprover("张系长");
CollegeApprover collegeApprover = new CollegeApprover("黄院长");
SchoolApprover schoolApprover = new SchoolApprover("刘校长");
// 设置各个处理者的下一位兜底处理者,设置环状处理
departmentApprover.setApprover(collegeApprover);
collegeApprover.setApprover(schoolApprover);
schoolApprover.setApprover(departmentApprover);
departmentApprover.processRequest(purchaseRequest);
}
}
注意细节:
将请求和处理分开,实现解耦,提高系统的灵活性
简化了对象,使对象不需要知道链的结构
性能会受到影响,特别是在链比较长的时候,因此需控制链中最大节点数量,一般通过在 Handler 中设置一个最大节点数量,在 setNext()方法中判断是否已经超过阀值,超过则不允许该链建立,避免出现超长链无意识地破坏系统性能
调试不方便。采用了类似递归的方式,调试时逻辑可能比较复杂
最佳应用场景:有多个对象可以处理同一个请求时,比如:多级请求、请假/加薪等审批流程、Java Web 中 Tomcat
对 Encoding 的处理、拦截器