积累知识,分享智慧,让成长之路不再孤单
设计模式概述
设计模式主要是为了解决某类重复出现的问题而出现的一套成功或有效的解决方案
设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,使用设计模式是为了可重用代码、让代码更容易被他人理解并且保证代码可靠性。
面向对象设计原则
设计原则 定义
单一职责原则 一个类只负责一个功能领域中的相应职责
开闭原则 软件实体应对扩展开放,而对修改关闭
里氏替换原则 所有引用基类对象的地方能够透明地使用其子类的对象(多态)
依赖倒置原则 抽象不应该依赖于细节,细节应该依赖于抽象
接口隔离原则 使用多个专门的接口,而不使用单一的总接口
迪米特法则 一个软件实体应当尽可能少地与其他实体发生相互作用
创建型模式
创建型模式主要用于描述如何创建对象
简单工厂模式
静态工厂模式,根据参数的不同返回不同的实例。
工厂角色
抽象产品角色
具体产品角色
工厂方法模式
定义一个创建对象的接口,允许子类决定实例化对象的类型,工厂模式使其创建过程延迟到子类进行。
例如:假设你在一个餐厅点餐,你可以选择汉堡、披萨或沙拉。每种食物都是由对应的厨师独立制作的。这里,每个厨师就是一个工厂,负责制作一种特定的食物。你只需要告诉服务员你要什么食物,服务员会将你的请求交给对应的厨师去制作。这就是工厂方法模式,通过工厂来生产相应的产品。
// 产品接口
interface Food {
void prepare();
void cook();
void serve();
}
// 具体产品1
class Burger implements Food {
@Override
public void prepare() {
System.out.println("Preparing burger...");
}
@Override
public void cook() {
System.out.println("Cooking burger...");
}
@Override
public void serve() {
System.out.println("Serving burger.");
}
}
// 具体产品2
class Pizza implements Food {
@Override
public void prepare() {
System.out.println("Preparing pizza...");
}
@Override
public void cook() {
System.out.println("Cooking pizza...");
}
@Override
public void serve() {
System.out.println("Serving pizza.");
}
}
// 工厂接口
interface FoodFactory {
Food createFood();
}
// 具体工厂1 - 汉堡工厂
class BurgerFactory implements FoodFactory {
@Override
public Food createFood() {
return new Burger();
}
}
// 具体工厂2 - 披萨工厂
class PizzaFactory implements FoodFactory {
@Override
public Food createFood() {
return new Pizza();
}
}
// 客户端代码
public class FactoryMethodExample {
public static void main(String[] args) {
FoodFactory burgerFactory = new BurgerFactory();
Food burger = burgerFactory.createFood();
burger.prepare();
burger.cook();
burger.serve();
FoodFactory pizzaFactory = new PizzaFactory();
Food pizza = pizzaFactory.createFood();
pizza.prepare();
pizza.cook();
pizza.serve();
}
}
抽象工厂模式
提供⼀个创建⼀系列相关或相互依赖对象的接口,而无需指定它们具体的类。
解决的问题是在⼀个产品族,存在多个不同类型的产品情况下,接口选择的问题
例如:假设你正在设计一个电子产品系列,包括手机、平板和笔记本电脑。每个系列有不同的品牌和型号。你可以创建一个抽象工厂,它负责创建整个系列的产品,如手机、平板和笔记本电脑。然后,你可以根据不同的品牌,比如苹果、三星和小米,来创建具体的工厂(如苹果工厂、三星工厂和小米工厂),每个具体的工厂生产对应品牌的产品。抽象工厂模式帮助你创建一族相关的产品系列。
工厂方法模式注重于创建一种类型(食物)的对象,
而抽象工厂模式注重于创建一组相关类型(电子产品)的对象。
// 手机接口
interface Phone {
void makeCall();
}
// 平板接口
interface Tablet {
void playGame();
}
// 笔记本电脑接口
interface Laptop {
void doWork();
}
// 具体手机 - 苹果手机
class ApplePhone implements Phone {
@Override
public void makeCall() {
System.out.println("Making a call with an Apple phone.");
}
}
// 具体手机 - 小米手机
class XiaomiPhone implements Phone {
@Override
public void makeCall() {
System.out.println("Making a call with a Xiaomi phone.");
}
}
// 具体平板 - 苹果平板
class AppleTablet implements Tablet {
@Override
public void playGame() {
System.out.println("Playing game on an Apple tablet.");
}
}
// 具体平板 - 小米平板
class XiaomiTablet implements Tablet {
@Override
public void playGame() {
System.out.println("Playing game on a Xiaomi tablet.");
}
}
// 具体笔记本电脑 - 苹果笔记本电脑
class AppleLaptop implements Laptop {
@Override
public void doWork() {
System.out.println("Doing work on an Apple laptop.");
}
}
// 具体笔记本电脑 - 小米笔记本电脑
class XiaomiLaptop implements Laptop {
@Override
public void doWork() {
System.out.println("Doing work on a Xiaomi laptop.");
}
}
// 抽象工厂接口
interface ElectronicFactory {
Phone createPhone();
Tablet createTablet();
Laptop createLaptop();
}
// 具体工厂 - 苹果电子产品工厂
class AppleFactory implements ElectronicFactory {
@Override
public Phone createPhone() {
return new ApplePhone();
}
@Override
public Tablet createTablet() {
return new AppleTablet();
}
@Override
public Laptop createLaptop() {
return new AppleLaptop();
}
}
// 具体工厂 - 小米电子产品工厂
class XiaomiFactory implements ElectronicFactory {
@Override
public Phone createPhone() {
return new XiaomiPhone();
}
@Override
public Tablet createTablet() {
return new XiaomiTablet();
}
@Override
public Laptop createLaptop() {
return new XiaomiLaptop();
}
}
// 客户端代码
public class AbstractFactoryExample {
public static void main(String[] args) {
ElectronicFactory appleFactory = new AppleFactory();
Phone apple = appleFactory.createPhone();
}
}
单例模式
保证⼀个类仅有⼀个实例,并提供⼀个访问它的全局访问点
● 懒汉模式
// 线程不安全
public class Single {
private static Single instance;
private Single() {};
public static Single getInstance() {
if(instance != null) return instance;
instance = new Single();
return instance;
}
}
// 线程安全
public class Single {
private static Single instance;
private Single() {};
public static synchronized Single getInstance() {
if(instance != null) return instance;
instance = new Single();
return instance;
}
}
● 饿汉模式 (线程安全)
public class Single {
private static Single instance = new Single();
private Single() {};
public static Single getInstance() {
return instance;
}
}
● 使用类的内部类 (线程安全)推荐
public class Single {
private static class SingleHolder {
private static Single instance = new Single();
}
private Single() {};
public static Single getInstance() {
return SingleHolder.instance;
}
}
● 双重锁校验 (线程安全)
public class Single {
private static Single instance;
private Single() {};
public static Single getInstance() {
if(instance != null) return instance;
synchronized(Single.class) {
if(instance == null) instance = new Single();
}
return instance;
}
}
● CAS AtomicReference (线程安全)
public class Single {
private static final AtomicReference<Single> INSTANCE = new AtomicReference<Single>();
private static Single instance;
private Single() {};
public static Single getInstance() {
for(;;) {
Single instance = INSTANCE.get();
if(instance != null) return instance;
INSTANCE.compareAndSet(null, new Single());
return INSTANCE.get();
}
}
}
● 枚举单例 (线程安全) 推荐
public enum Singleton {
INSTANCE;
public void test() {
System.out.println("hi~");
}
}
@Test
public void test() {
Singleton.INSTANCE.test();
}
该方式提供了串行化机制。在继承场景下不可用
原型模式
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模式主要解决的问题是创建重复对象
对于数据的获取可能需要从数据库中获取,或者从远程的 RPC 中获取,效率较低,因此在原型模式中非常重要的手段就是克隆,实现 Cloneable 接口。
举例:
public class Email implements Cloneable{
private Attachment attachment;
public Email() {
attachment = new Attachment();
}
public Email clone() {
try {
return (Email) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
public Attachment getAttachment() {
return attachment;
}
}
public class Attachment {
}
public class Client {
public static void main(String[] args) {
Email email = new Email();
Email cloneEmail = email.clone();
System.out.println(email == cloneEmail); // false
System.out.println(email.getAttachment() == cloneEmail.getAttachment()); // true
}
}
深拷贝:
public class Email implements Serializable {
private Attachment attachment;
public Email() {
attachment = new Attachment();
}
public Object deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bao = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bao);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
public Attachment getAttachment() {
return attachment;
}
}
public class Attachment implements Serializable {
}
public class Client {
public static void main(String[] args) throws IOException, ClassNotFoundException {
Email email = new Email();
Email clone = (Email) email.deepClone();
System.out.println(email == clone); // false
System.out.println(email.getAttachment() == clone.getAttachment()); // false
}
}
```
建造者模式
将⼀个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

● 产品(Product):表明需要构建的产品对象
● 抽象建造者(Builder):抽象出来的构建者类,用于定义创建对象所需的步骤以及创建的步骤的调用过程
● 具体建造者(ConcreteBuilder):抽象建造者的具体实现,对于不同的创建过程可以用不同的类进行实现
● 指挥者(Director):使用 Builder 的类,提供给调用方使用,调用方通过使用指挥者来获取产品
```java
// 产品类,定义产品的三个部分
public class Product {
private Object part1;
private Object part2;
private Object part3;
public void setPart1(Object part1) {
this.part1 = part1;
}
public void setPart2(Object part2) {
this.part2 = part2;
}
public void setPart3(Object part3) {
this.part3 = part3;
}
@Override
public String toString() {
return "Product{" +
"part1=" + part1 +
", part2=" + part2 +
", part3=" + part3 +
'}';
}
}
// 抽象建造者类,构建了一个产品对象,并定义了构建产品三个部分所需要的三个方法以及获取产品的方法
public abstract class Builder {
protected Product product = new Product();
public abstract void buildPart1();
public abstract void buildPart2();
public abstract void buildPart3();
public abstract Product getProduct();
}
// 具体建造者 1
public class ConcreteBuilder1 extends Builder{
@Override
public void buildPart1() {
product.setPart1("builder 1 set part 1.");
}
@Override
public void buildPart2() {
product.setPart2("builder 1 set part 2.");
}
@Override
public void buildPart3() {
product.setPart3("builder 1 set part 3.");
}
@Override
public Product getProduct() {
System.out.println("builder 1 build product.");
return product;
}
}
// 具体建造者 2
public class ConcreteBuilder2 extends Builder {
@Override
public void buildPart1() {
product.setPart1("builder 2 set part 1.");
}
@Override
public void buildPart2() {
product.setPart2("builder 2 set part 2.");
}
@Override
public void buildPart3() {
product.setPart3("builder 2 set part 3.");
}
@Override
public Product getProduct() {
System.out.println("builder 2 build product.");
return product;
}
}
// 指挥者对象
public class Director {
private Builder builder;
public Director(Builder builder) {
this.builder = builder;
}
public Product construct() {
builder.buildPart1();
builder.buildPart2();
builder.buildPart3();
Product product = builder.getProduct();
return product;
}
}
// 调用
public static void main(String[] args) {
Director director1 = new Director(new ConcreteBuilder1());
Product product1 = director1.construct();
System.out.println(product1);
System.out.println("==================================");
Director director2 = new Director(new ConcreteBuilder2());
Product product2 = director2.construct();
System.out.println(product2);
}
```
场景:模拟装修公司对于设计出一些套餐装修服务的场景
::: 不使用构建者模式可能是创建装修服务时不断的if else ,进行扩展时继续堆加代码
实现上:在物料方面可以定义一个统一的接口标准,使各物料实现接口完成各自的功能;DecorationPackageMenu 实现
IMenu(构建过程统一规范) 接口作为构建过程中的填充器,衔接物料和创建者的内容。
## 结构型模式
结构型模式主要用于描述如何实现类或对象的组合
将对象和类组装成较大的结构,并保持结构的灵活和高效。
### 适配器模式
包装器(Wrapper)模式
适配器模式的主要作用是将原本不兼容的接口,通过适配修改做到统一。
将多种差异化类型的接口做统一输出
例如:对于多种 MQ,可以定义一个统一的 MQ 接口,将各 MQ 与统一接口进行适配,可以是字段的转换
Targe:目标接口,定义客户要用的特定领域的接口,可以说抽象类或接口或类,由于Java不支持多继承,只能说接口
Adapter:适配器类,可以调用另一个接口,作为一个转换求,对 Adaptee 和 Target 进行适配。在类适配器中,通过实现 Target 接口并继承 Adaptee 使得二者产生关联;在对象适配器中,通过继承 Target 并关联一个 Adaptee 对象使得二者产生关联。
Adaptee:适配者类,被适配的角色,它定义了一个已经存在的接口,这个接口需要适配。
适用场景:系统需要使用一些现有的类,而这些类的接口不符合系统的需求。

● 类适配器
```java
public interface Target {
void request();
}
public class Adaptee {
public void specificRequest() {
System.out.println("适配者..");
}
}
public class Adapter extends Adaptee implements Target{
@Override
public void request() {
super.specificRequest();
}
}
```
● 对象适配器
```java
public interface Target {
void request();
}
public class Adaptee {
public void specificRequest() {
System.out.println("适配者..");
}
}
public class Adapter implements Target{
private Adaptee adaptee = new Adaptee();
public Adapter() {
}
public Adapter(Adaptee adaptee) {
this.adaptee = adaptee;
}
@Override
public void request() {
adaptee.specificRequest();
}
}
public class Client {
public static void main(String[] args) {
Target target = new Adapter();
target.request();
}
}
```
### 桥接模式
桥接模式的主要作用是通过将抽象部分和实现部分分离,使他们都可以独立变化。
● 将抽象与实现分离,选择支付时有多种支付方式,每种支付方式有多种支付的手段。
例如:用户选择支付时,可以使用微信或支付宝,通过密码,人脸,指纹进行支付;桥接点即为支付模式的选择。

● Abstraction(抽象类)
○ 定义抽象类的接口,一般是抽象类而不是接口。里面维护一个 Implementor (支付方式)
● RefinedAbstraction(扩充抽象类)
○ 实现了 Abstraction 的类,可以调用 Implementor 中的方法(微信支付/支付宝支付)
● Implementor(实现类的接口)
○ 定义基本操作(支付手段)
● ConcreteImplementor(具体实现类)
○ 具体操作(密码、指纹、人脸)
```java
public interface IPayMode {
boolean security(String uId);
}
public class PayCypher implements IPayMode{
public boolean security(String uId) {
logger.info("密码支付,风控校验环境安全");
return true;
}
}
public class PayFaceMode implements IPayMode{
public boolean security(String uId) {
logger.info("人脸支付,风控校验脸部识别");
return true;
}
}
public class PayFingerprintMode implements IPayMode{
public boolean security(String uId) {
logger.info("指纹支付,风控校验指纹信息");
return true;
}
}
public abstract class Pay {
protected IPayMode payMode;
public Pay(IPayMode payMode) {
this.payMode = payMode;
}
public abstract String transfer(String uId, String tradeId, BigDecimal amount);
}
public class WxPay extends Pay {
public WxPay(IPayMode payMode) {
super(payMode);
}
public String transfer(String uId, String tradeId, BigDecimal amount) {
boolean security = payMode.security(uId);
if (!security) {
return "0001";
}
return "0000";
}
}
public class ZfbPay extends Pay {
public ZfbPay(IPayMode payMode) {
super(payMode);
}
public String transfer(String uId, String tradeId, BigDecimal amount) {
boolean security = payMode.security(uId);
if (!security) {
return "0001";
}
return "0000";
}
}
public class Client() {
@Test
public void test_pay() {
System.out.println("\r\n模拟测试场景;微信支付、人脸方式。");
Pay wxPay = new WxPay(new PayFaceMode());
wxPay.transfer("weixin_1092033111", "100000109893", new BigDecimal(100));
System.out.println("\r\n模拟测试场景;支付宝支付、指纹方式。");
Pay zfbPay = new ZfbPay(new PayFingerprintMode());
zfbPay.transfer("jlu19dlxo111","100000109894",new BigDecimal(100));
}
}
```
### 组合模式
将对象组合成树形结构以表示"部分-整体"的层次结构。组合模式使得⽤户对单个对象(叶子)和组合对象(容器)的使⽤具有⼀致性
树形目录结构:文件、文件夹
组合模式包含角色:
● Component(抽象构件)
● Leaf(叶子构件)
● Composite(容器构件)

盘子中由 ArrayList 作为容器存储某种水果或盘子。
此例中抽象构件只有 eat()方法,没有子构件操作的相关方法(即盘子添加、删除操作),叶子构件无法调用添加和删除方法,对于客户端而言是安全的,但是无法通过抽象构件来定义容器构件,叶子构件和容器构件需要有不同的类型定义,是不透明的,系统的灵活性和扩展性会受到影响。
可以在 抽象构件中定义所有方法,子构件中实现所有方法,对部分方法(用不到的方法)可以直接进行异常抛出或是信息提示。
安全组合模式:抽象构件不声明操作方法,只有业务方法
```java
// 举例:水果盘
/**
* Component
*/
public abstract class MyElement {
public abstract void eat();
}
/**
* Leaf
*/
public class Apple extends MyElement{
@Override
public void eat() {
System.out.println("eat apple.");
}
}
public class Banana extends MyElement {
@Override
public void eat() {
System.out.println("eat banana.");
}
}
public class Pear extends MyElement {
@Override
public void eat() {
System.out.println("eat pear.");
}
}
/**
* Composite
*/
public class Plate extends MyElement {
private ArrayList list = new ArrayList();
public void add(MyElement element) {
list.add(element);
}
public void remove(MyElement element) {
list.remove(element);
}
@Override
public void eat() {
for (Object object : list) {
((MyElement) object).eat();
}
}
}
public class Client {
public static void main(String[] args) {
MyElement obj1, obj2, obj3;
Plate plate1, plate2;
obj1 = new Apple();
obj2 = new Pear();
plate1 = new Plate();
plate1.add(obj1);
plate1.add(obj2);
obj3 = new Banana();
plate2 = new Plate();
plate2.add(plate1);
plate2.add(obj3);
plate2.eat();
}
}
```
-------------------------------------------------------------------------------------------
例:寻找 [男/29] 的节点
● 决策树的处理流程:在进行组和形成一棵树后,由 LogicFilter 定义决策的过滤器,LogicFilter 定义逻辑决策器和获取决策值,具体的执行过程由执行引擎 IEngine 实现
Long filter(String matterValue, List<TreeNodeLink> treeNodeLineInfoList);
String matterValue(Long treeId, String userId, Map<String, String> decisionMatter);
○ BasicLogic 实现 LogicFilter ,提供最基本的通用的方法
■ filter:根据决策值以及节点之间的链接条件得到满足条件的下一个节点 Id
■ matterValue:获取决策值的方法定义为抽象方法,由具体的逻辑实现类提供,比如:UserAgeFilter,UserGenderFilter
○ IEngine 定义决策的统一的接口
在进行扩展时只需要添加新的 Filter 以及将该 Filter 配置到执行引擎当中即可::: 决策值:需要进行比较的条件,比如性别,年龄::: 决策物料:最终寻找节点所依据的条件值,(包括决策值和具体条件)比如,年龄:29,性别:男::: 子叶:表示条件的类型,同决策值::: 果实:最终结果
EngineResult process(final Long treeId, final String userId, TreeRich treeRich, final Map<String, String> decisionMatter);
■ EngineConfig :决策节点的配置,即添加执行引擎要用到的 filter,如 UserAgeFilter ...
■ EngineBase:基础决策引擎功能,提供决策树流程的处理过程
● 定义 process 抽象方法
● engineDecisionMaker :具体的决策过程,返回最终果实
■ TreeEngineHandle 继承 EngineBase 实现 process 并返回决策结果 (模板模式)
● 这里只做了调用 EngineBase 中的 engineDecisionMaker 并将结果封装
### 装饰器模式
装饰器模式的主要作用是在不改变原有类的基础上给类新增功能(除装饰器模式,还可以使用继承和 AOP)
别名:包装器(Wrapper)同适配器别名
场景:字节流、字符流 ....
装饰器主要解决的是直接继承下因功能的不断横向扩展导致子类膨胀的问题。
核心:1) 继承了处理接⼝、2)提供了构造函数、3)覆盖了⽅法
可以踢掉对⼦类继承的⽅式实现逻辑功能扩展
1. 抽象构件角色(Component)- 定义抽象接口
2. 具体构件角色(ConcreteComponent)- 实现抽象接口,可以是一组
3. 装饰器角色(Decorator)- 定义抽象类并继承接口中的方法,保证一致性
4. 具体装饰角色(ConcreteDecorator)- 扩展装饰具体的实现逻辑

```java
public abstract class Component {
public abstract void operation();
}
public class ConcreteComponent extends Component {
@Override
public void operation() {
System.out.println("initial operation...");
}
}
public class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
public void operation() {
component.operation();
}
}
public class ConcreteDecorator extends Decorator {
public ConcreteDecorator(Component component) {
super(component);
}
public void operation() {
super.operation();
addedBehavior();
}
private void addedBehavior() {
System.out.println("new method.");
}
}
public class Client {
public static void main(String[] args) {
Component component = new ConcreteComponent();
component.operation();
System.out.println("---------");
ConcreteDecorator decorator = new ConcreteDecorator(component);
decorator.operation();
}
}
```
模拟单独登录场景:
SsoDecorator 抽象类主要完成了对 HandlerInterceptor 的实现,当装饰器角色实现接口后会提供了构造函数,入参就是实现的接口实现类
即:LoginSsoDecorator 调用父类中的处理方法,其父类的处理方法由 HandlerInterceptor 的实现类 SsoInterceptor 实现具体方法。这样做使得具体装饰角色在进行扩展其逻辑服务时并不会直接依赖于其它实体,而通过父类完成方法的实现。体现迪米特原则,其父类也就是装饰器角色通过实现构建角色接口并提供接口入参从而关联到具体方法的实现类上。
::: 一个业务逻辑的实现过程中要调用其他的业务逻辑而采取的模式
张三想要和李四玩,张三通过他爹,他爹通过李四爹,李四爹把李四推给张三爹,最后引入张三。
### 外观模式
外观模式也叫门面模式,主要解决的是降低调用方的使用接口的复杂逻辑组合。调用方与实际的接口提供方提供了一个中间层,用于包装逻辑提供 API 接口。
网站首页包含其他子项目的链接。
```java
public class Facede {
private SubSystemA obj1 = new SubSystemA();
private SubSystemB obj2 = new SubSystemB();
private SubSystemC obj3 = new SubSystemC();
public void method() {
obj1.method();
obj2.method();
obj3.method();
}
}
享元模式
享元模式主要作用是共享通用对象,减少内存的使用,提升系统的访问效率。
例如:数据库连接池的使用、多线程的使用。
代理模式
为其他对象提供⼀种代理以控制对这个对象的访问
● 静态代理
● 动态代理
行为型模式
行为型模式主要用于描述类或对象怎样交互以及怎样分配职责
责任链模式
责任链模式的主要作用是解决一组服务中的先后执行处理关系
责任链模式:为了避免请求发送者与多个请求耦合在一起,将所有请求的处理者通过前一对象记住下一对象的引用而连成一条链
● Handler(抽象处理者)
● ConcreteHandler(具体处理者)
public abstract class Handler {
protected Handler successor;
public Handler(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(String request);
}
public class concreteHandler extends Handler {
public void handleRequest(String request) {
if (请求 request 满足条件) {
....
} else {
super.successor.handleRequest(request);
}
}
}
例:OA 系统的一个假条审批,员工请求天数小于 3 天由主任审批,大于 3 天小于 10 天由经历审批,大于 10 天小于 30 天由总经理审批
public class LeaveRequest {
private String name;
private int leaveDays;
...
}
public abstract class Leader {
protected String name;
protected Leader successor;
public Leader(String name) {
this.name = name;
}
public void setSuccessor(Leader successor) {
this.successor = successor;
}
public abstract void handleRequest(LeaveRequest request);
}
public class Director extends Leader {
public Director(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 3) {
System.out.println("主任" + name + "审批员工" + request.getName() + "请假" + request.getLeaveDays() + "天");
} else {
if (super.successor != null) {
super.successor.handleRequest(request);
}
}
}
}
public class Manager extends Leader {
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 10) {
System.out.println("经理" + name + "审批员工" + request.getName() + "请假" + request.getLeaveDays() + "天");
} else {
if (super.successor != null) {
super.successor.handleRequest(request);
}
}
}
}
public class GeneralManager extends Leader {
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if (request.getLeaveDays() < 30) {
System.out.println("总经理" + name + "审批员工" + request.getName() + "请假" + request.getLeaveDays() + "天");
} else {
System.out.println("超出范围 !!!!!!!");
}
}
}
public class Client {
public static void main(String[] args) {
Leader director, manager, generalManager;
director = new Director("王明");
manager = new Manager("赵强");
generalManager = new GeneralManager("李波");
director.setSuccessor(manager);
manager.setSuccessor(generalManager);
LeaveRequest lr1 = new LeaveRequest("张三", 2);
LeaveRequest lr2 = new LeaveRequest("李四", 2);
LeaveRequest lr3 = new LeaveRequest("王五", 15);
LeaveRequest lr4 = new LeaveRequest("赵六", 45);
director.handleRequest(lr1);
director.handleRequest(lr2);
director.handleRequest(lr3);
director.handleRequest(lr4);
}
}
命令模式
将⼀个请求封装成⼀个对象,从⽽使我们可以⽤不同的请求对客户进⾏参数化。
例如: Ctrl + c , Ctrl + v
场景模拟:饭店点餐, 点餐人员将所点菜系交给小二,小二将菜系交给各个厨师
命令 ---- 命令调用者 — 命令实现者
命令实现(菜品)、逻辑实现(厨师)、调⽤者(⼩⼆)
● Command(抽象命令类)
● ConcreteCommand(具体命令类)
● Invoker(调用者)
● Receiver(接收者)
发送者和接收者没有直接关系,通过命令对象调用实现。
public abstract class Command {
public abstract void execute();
}
public class ConcreteCommand extends Command {
private Receiver receiver = new Receiver();
public void execute() {
receiver.action();
}
}
public class Invoker {
private Command command;
public Invoker(Command command) {
this.command = command;
}
public void call() {
command.execute();
}
}
public class Receiver {
public void action() {}
}
public class Client {
public static void main(String[] args) {
Invoker invoker = new Invoker(new ConcreteCommand());
invoker.call();
}
}
迭代器模式
提供⼀种⽅法顺序访问⼀个聚合对象中各个元素, ⽽⼜⽆须暴露该对象的内部表示。
例: Iterator 遍历
● Iterator(抽象迭代器):定义遍历的相关方法
● ConcreteIterator(具体迭代器)
● Aggregate(抽象聚合类):提供创建迭代器对象的方法
● ConcreteAggregate(具体聚合类):包含对象集合以及创建迭代器对象的方法
中介者模式
⽤⼀个中介对象来封装⼀系列的对象交互,中介者使各对象不需要显式地相互引⽤,从⽽使其耦合松散,⽽且可以独⽴地改变它们之间的交互
中介者模式要解决的就是复杂功能应⽤之间的重复调用,在这中间添加⼀层中介者包装服务,对外提供简单、通⽤、易扩展的服务能⼒
MyBatis ORM 框架采用中介者模式
备忘录模式
在不破坏封装性的前提下,捕获⼀个对象的内部状态,并在该对象之外保存这个状态。
备忘录模式是以可以恢复或者说回滚,配置、版本、悔棋为核⼼功能的设计模式
观察者模式
定义对象间的⼀种⼀对多的依赖关系,当⼀个对象的状态发⽣改变时,所有依赖于它的对象都得到通知并被⾃动更新。
● Subject(目标):定义观察者集合,增删观察者,通知观察者。
● ConcreteSubject(具体目标)
● Observer(观察者)
● ConcreteObserver(具体观察者)
public abstract class Subject{
protected ArrayList observers = new ArrayList();
public abstract void attach(Observer o);
public abstract void detach(Observer o);
public abstract void notify();
}
public class concreteSubject extends Subject{
public abstract void attach(Observer o){
observers.add(o);
}
public abstract void detach(Observer o){
observers.remove(o);
}
public abstract void notify(){
for(Object obj:observers){
(Observer)obj.update();
}
}
}
public interface Observer{
void update();
}
...
状态模式
允许对象在内部状态发⽣改变时改变它的⾏为,对象看起来好像修改了它的类。
状态模式描述的是⼀个⾏为下的多种状态变更,⽐如我们最常⻅的⼀个⽹站的⻚⾯,在你登录与不登录
下展示的内容是略有差异的( 不登录不能展示个⼈信息 ),⽽这种 登录 与 不登录 就是我们通过改变状态,
⽽让整个⾏为发⽣了变化。
● Context
● State
● ConcreteStateA
● ConcreteStateB
策略模式
定义⼀系列的算法,把它们⼀个个封装起来,并且使它们可相互替换。
应用场景:一般是具有同类可替代的行为逻辑算法场景
例:对于商品打折,有满减、直减、等… … 定义打折方法的接口,再定义 Context 上下文依赖 该接口,各种策略实现接口,通过 上下文实现对具体策略的选择,类似适配器…
● Context
● Strategy
● ConcreteStrategyA
● ConcreteStrategyB
public abstract class AbstractStrategy {
public abstract void algorithm();
}
public class ConcreteStrategyA extends AbstractStrategy {
public void algorithm() {
System.out.println("A.");
}
}
public class ConcreteStrategyB extends AbstractStrategy {
public void algorithm() {
System.out.println("B.");
}
}
public class Context {
private AbstractStrategy strategy;
public void setStrategy(AbstractStrategy strategy) {
this.strategy = strategy;
}
public void algorithm() {
strategy.algorithm;
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context();
AbstractStrategy strategy = new ConcreteStrategyA();
context.setStrategy(strategy);
context.algorithm();
}
}
模板方法模式
定义⼀个操作中的算法的⻣架,⽽将⼀些步骤延迟到⼦类中。模板⽅法使得⼦类可以不改变⼀个算法的结构即可定义该算法的某些特定步骤。
模板模式的核心是通过在抽象类中定义抽象方法的执行顺序,并将抽象方法设定为只有子类实现,但不设计独立访问的方法。
访问者模式
主要将数据结构与数据操作分离
解释器模式
…