Java设计模式学习笔记

0. 七大原则

  • 单一职责原则:一个类只执行一个职责,控制类的粒度,将对象解耦,提高内聚性
  • 接口隔离原则:一个类对另一个类的依赖建立在最小接口上
  • 依赖倒转原则:面向接口变成,不要面向实现变成
  • 里氏替换原则:继承必须确保超类的所有性质在子类中仍然成立
  • 开闭原则:对扩展开放,对修改关闭
  • 迪米特法则(最少知道原则):与直接朋友交流,不和陌生人交流(会产生大量中介类)
  • 合成复用原则:尽量先使用组合或聚合等关联关系来实现,其次才考虑继承关系来实现

分类

  • 创建型模式:单例模式,工厂模式,抽象工厂模式,建造者模式,原型模式
  • 结构型模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式
  • 行为模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、责任链模式、访问者模式

1. 单例模式

保证全局只能有一个实例对象

1.1 饿汉式

package singleteton;

/**
 * @program: design-patterns
 * @description: 饿汉式单例
 * @author: ambition
 * @create: 2022-08-19 15:17
 * 缺点:不管有没有用到都会初始化,如果对象很大,即使没用也会占用大量内存空间
 **/

public class Hungry {
    private static final Hungry HUNGRY = new Hungry();
	//构造器私有化
    private Hungry() {
    }

    public static Hungry getInstance() {
        return HUNGRY;
    }
}

1.2 懒汉式

1.2.1 简单懒汉式

package singleteton;
/**
 * @program: design-patterns
 * @description: 懒汉式单例
 * @author: AMBITION
 * @create: 2022-08-19 15:24
 * 缺点:不是线程安全的
 **/
public class Lazy {
    private static Lazy LAZY;

    private Lazy() {}

    public static Lazy getInstance() {
        if (null == LAZY) {
            LAZY = new Lazy();
        }
        return LAZY;
    }
}

1.2.2 双重检测锁模式(DCL懒汉式)

package singleteton;

/**
 * @program: design-patterns
 * @description: 懒汉式单例
 * @author: AMBITION
 * @create: 2022-08-19 15:24
 **/

public class Lazy {

    /**
     * 一定要加volatile 防止指令重排导致的线程不安全问题
     */
    private static volatile Lazy LAZY;

    private Lazy() {}

    public static Lazy getInstance() {
        if (null == LAZY) {
            synchronized (Lazy.class) {
                if (null == LAZY) {
                    LAZY = new Lazy();
                }
            }
        }
        return LAZY;
    }
    
}

1.2.3 静态内部类

package singleteton;

/**
 * @program: design-patterns
 * @description: 懒汉式单例
 * @author: AMBITION
 * @create: 2022-08-19 15:24
 **/

public class Lazy {
    private static class LazyHolder {
        private static final Lazy LAZY = new Lazy();
    }

    /**
     * 静态内部类在实际使用到的时候才会加载,并且因为是静态常量对象只加载一次,jvm保证一定线程安全,
     * @return 
     */
    public static Lazy getInstance() {
        return LazyHolder.LAZY;
    }
}

1.3 枚举式单例

package singleteton;
/**
 * 优点:枚举没有构造方法,不会被反射破坏单例
 */
public enum Singleteton {
    SINGLETETON;

    public void say() {
        System.out.println("Hello World!");
    }
    public static void main(String[] args) {
        Singleteton.SINGLETETON.say();
    }
}

1.4 举例:JDK中的Runtime.java 用的就是饿汉式单例

2. 工厂模式

2.1 简单工厂模式

通过工厂类去获得新对象而不是自己new一个,符合迪米特法则
但是当新增一个种类时就必须要修改工厂类,不符合开闭原则
public interface Car {
    /**
     * 打印名字
     */
    void name();
}
public class Wuling implements Car {
    @Override
    public void name() {
        System.out.println("五菱宏光!!!");
    }
}
public class Tesla implements Car {
	@Override
    public void name() {
        System.out.println("tesla!!!");
    }
}
public class CarFactory {
    public static Car getCar(String name) {
        if ("五菱宏光".equals(name)) {
            return new Wuling();
        } else if ("tesla".equals(name)) {
            return new Tesla();
        }
        return null;
    }
}
public class Consumer {
    public static void main(String[] args) {
        /*Car car1 = new Wuling();
        Car car2 = new Tesla();
        car1.name();
        car2.name();*/

        Car car1 = CarFactory.getCar("五菱宏光");
        Car car2 = CarFactory.getCar("tesla");
        car1.name();
        car2.name();
    }
}

2.2 工厂方法模式

每个种类都对应一个工厂,当新增种类的时候就可以横向扩展,避免违反开闭原则
但是会导致代码复杂度变高
public class Dazhong implements Car {
    public void name() {
        System.out.println("大众!!!");
    }
}
public class WulingFactory {
    public static Car getWuling() {
        return new Wuling();
    }
}
public class TeslaFactory {
    public static Car getTesla() {
        return new Tesla();
    }
}
public class DazhongFactory {
    public static Car getDazhong(){
        return new Dazhong();
    }
}
public class Consumer {
    public static void main(String[] args) {
        /*Car car1 = new Wuling();
        Car car2 = new Tesla();
        car1.name();
        car2.name();*/

        /*Car car1 = CarFactory.getCar("五菱宏光");
        Car car2 = CarFactory.getCar("tesla");
        car1.name();
        car2.name();*/

        Car car1 = WulingFactory.getWuling();
        Car car2 = TeslaFactory.getTesla();
        Car car3 = DazhongFactory.getDazhong();
        car1.name();
        car2.name();
        car3.name();

    }
}

3. 抽象工厂模式

围绕一个超级工厂创建其他工厂,该工厂又称为其他工厂的工厂 
相比普通工厂更抽象,将一系列的产品统一到一起创建
缺点是抽象工厂规定了所有可能被创建的产品集,一旦增加产品,对应的所有实现类必须跟着一起修改
适用于产品种类比较稳定的场景
  • 定义抽象工厂
public interface AbstractFactory {
    IPhone getPhone();
    IWifi getWifi();
}
  • 定义具体工厂,并继承抽象工厂
public class HuaweiFactory implements AbstractFactory {
    @Override
    public IPhone getPhone() {
        return new HuaweiPhone();
    }

    @Override
    public IWifi getWifi() {
        return new HuaweiWifi();
    }
}
public class XiaomiFactory implements AbstractFactory {
    @Override
    public IPhone getPhone() {
        return new XiaomiPhone();
    }

    @Override
    public IWifi getWifi() {
        return new XiaomiWifi();
    }
}
public interface IPhone {
    void call();
    void sms();
    void music();
    void webSurfing();
}

public interface IWifi {
    void wifiSupport();
    void setting();
    void reset();
}
public class HuaweiPhone implements IPhone {
    @Override
    public void call() {
        System.out.println("华为手机正在打电话……");
    }

    @Override
    public void sms() {
        System.out.println("华为手机正在发短信……");
    }

    @Override
    public void music() {
        System.out.println("华为手机正在播放音乐……");
    }

    @Override
    public void webSurfing() {
        System.out.println("华为手机正在网上冲浪……");
    }
}
public class HuaweiWifi implements IWifi {
    @Override
    public void wifiSupport() {
        System.out.println("华为路由器正在提供无线上网服务……");
    }

    @Override
    public void setting() {
        System.out.println("华为路由器正在更改设置……");

    }

    @Override
    public void reset() {
        System.out.println("华为路由器正在回复出厂设置……");

    }
}
public class XiaomiPhone implements IPhone {
    @Override
    public void call() {
        System.out.println("小米手机正在打电话……");
    }

    @Override
    public void sms() {
        System.out.println("小米手机正在发短信……");
    }

    @Override
    public void music() {
        System.out.println("小米手机正在播放音乐……");
    }

    @Override
    public void webSurfing() {
        System.out.println("小米手机正在网上冲浪……");
    }
}
public class XiaomiWifi implements IWifi {
    @Override
    public void wifiSupport() {
        System.out.println("小米路由器正在提供无线上网服务……");
    }

    @Override
    public void setting() {
        System.out.println("小米路由器正在更改设置……");

    }

    @Override
    public void reset() {
        System.out.println("小米路由器正在回复出厂设置……");

    }
}

4. 建造者模式

将一个复杂对象的构建和表示分离,使得同样的构建过程可以有不同的表示
  • 有指挥者的模式
public abstract class Builder {
    abstract void buildA();
    abstract void buildB();
    abstract void buildC();
    abstract void buildD();
    abstract Product getProduct();

}
// 被创建的商品
public class Product {
    private String a;
    private String b;
    private String c;
    private String d;

    @Override
    public String toString() {
        return "Product{" +
                "a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }

    public String getA() {
        return a;
    }

    public void setA(String a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }

    public String getC() {
        return c;
    }

    public void setC(String c) {
        this.c = c;
    }

    public String getD() {
        return d;
    }

    public void setD(String d) {
        this.d = d;
    }
}
//工人提供建造功能
public class Worker extends Builder{
    private Product product;

    public Worker() {
        product = new Product();
    }

    @Override
    void buildA() {
        product.setA("挖地基");
        System.out.println("挖地基");
    }

    @Override
    void buildB() {
        product.setB("搭钢筋");
        System.out.println("搭钢筋");
    }

    @Override
    void buildC() {
        product.setC("接水电");
        System.out.println("接水电");
    }

    @Override
    void buildD() {
        product.setD("贴瓷砖");
        System.out.println("贴瓷砖");
    }

    @Override
    public Product getProduct(){
        return product;
    }
}
//指挥者 指挥建造过程
public class Director {
    public Product buildOne(Builder builder){
        builder.buildA();
        builder.buildB();
        builder.buildC();
        builder.buildD();
        return builder.getProduct();
    }

    public Product buildTwo(Builder builder){
        builder.buildA();
        builder.buildC();
        builder.buildB();
        builder.buildD();
        return builder.getProduct();
    }
}
// 测试代码
		Worker worker = new Worker();
        Director director = new Director();
        Product product = director.buildTwo(worker);
        System.out.println(product.toString());
  • 无指挥者 链式调用
public abstract class BaseBuilder {
    abstract BaseBuilder buildA(String msg);
    abstract BaseBuilder buildB(String msg);
    abstract BaseBuilder buildC(String msg);
    abstract BaseBuilder buildD(String msg);
    abstract Product getProduct();

}
public class MyWorker extends BaseBuilder {
    private Product product;
    //提供一个默认的情况
    public MyWorker() {
        this.product = new Product();
        this.product.setA("可乐");
        this.product.setB("汉堡");
        this.product.setC("鸡翅");
        this.product.setD("番茄酱");
    }
    @Override
    public BaseBuilder buildA(String msg) {
        this.product.setA(msg);
        return this;
    }

    @Override
    public BaseBuilder buildB(String msg) {
        this.product.setB(msg);
        return this;
    }

    @Override
    public BaseBuilder buildC(String msg) {
        this.product.setC(msg);
        return this;
    }

    @Override
    public BaseBuilder buildD(String msg) {
        this.product.setD(msg);
        return this;
    }

    @Override
    public Product getProduct() {
        return this.product;
    }
}
// 测试代码
		MyWorker worker1 = new MyWorker();
        Product product1 = worker1.getProduct();
        System.out.println(product1.toString());
        worker1.buildA("雪碧");
        worker1.buildB("鸡腿");
        worker1.buildC("蛋挞");
        worker1.buildD("沙拉酱");
        Product product2 = worker1.getProduct();
        System.out.println(product2.toString());

5. 原型模式

  • 浅拷贝
package prototype;
import java.util.Date;
public class Sheep implements Cloneable {
    private String name;
    private Date birthday;
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public Sheep(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
        @Override
    public String toString() {
        return "Sheep{" +
                "name='" + name + '\'' +
                ", birthday=" + birthday +
                '}';
    }
}

public class TestMain {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date date = new Date();
        Sheep sheep = new Sheep("Dolly",date);
        Sheep sheep1 = (Sheep) sheep.clone();
        System.out.println(sheep.hashCode());
        System.out.println(sheep.toString());
        System.out.println(sheep1.hashCode());
        System.out.println(sheep1.toString());
        date.setTime(485641564);
        System.out.println(sheep.toString());
        System.out.println(sheep1.toString());
        
    }
}
  • 深拷贝:改造克隆方法
    @Override
    public Sheep clone() throws CloneNotSupportedException {
        Sheep sheep = (Sheep) super.clone();
        sheep.setBirthday((Date) this.birthday.clone());
        return sheep;
    }

6. 适配器模式

6.1 类适配器:继承和实现

电压问题:电源电压220V,手机充电电压5V,充电机适配电压
缺点:Java是单继承,一次只能适配一个类
package adapter;
/**
 * @description: 被适配者
 **/
public class Voltage220V {
    public int output220V() {
        int voltage = 220;
        System.out.println("电源电压:" + voltage + "V");
        return voltage;
    }
}

package adapter;
/**
 * @program: design-patterns
 * @description: 适配器接口
 **/
public interface IVoltage5V {
    int output5V();
}

package adapter;
/**
 * @description: 适配器实现
 **/
public class VoltageAdapter extends Voltage220V implements IVoltage5V {

    @Override
    public int output5V() {
        int v220 = super.output220V();
        System.out.println("适配器接收电压:" + v220 + "V");
        int v5 = v220 / 44;
        System.out.println("适配器输出电压:" + v5 + "V");
        return v5;
    }
}

package adapter;
/**
 * @description: 手机
 **/
public class Phone {
    public void charging(IVoltage5V iVoltage5V) {
        int voltage = iVoltage5V.output5V();
        if (voltage == 5){
            System.out.println("电压正常:" + voltage + "V,开始充电!");
        } else {
            System.out.println("电压异常:" + voltage + "V,无法充电!");
        }

    }
}

public class TestAdapter {
    public static void main(String[] args) {
        Phone phone = new Phone();
        VoltageAdapter voltageAdapter = new VoltageAdapter();
        phone.charging(voltageAdapter);
    }
}

6.2 对象适配器

被适配者通过聚合的方式引入到适配器中
package adapter;
/**
 * @description: 适配器实现
 **/
public class VoltageAdapter implements IVoltage5V {

    private Voltage220V voltage220V;

    public VoltageAdapter(Voltage220V voltage220V) {
        this.voltage220V = voltage220V;
    }

    @Override
    public int output5V() throws Exception {
        if (null != voltage220V) {
            int v220 = voltage220V.output220V();
            System.out.println("适配器接收电压:" + v220 + "V");
            int v5 = v220 / 44;
            System.out.println("适配器输出电压:" + v5 + "V");
            return v5;
        } else {
            throw new Exception("没有插上电源");
        }

    }
}

public class TestAdapter {
    public static void main(String[] args) throws Exception {
        Phone phone = new Phone();
        VoltageAdapter voltageAdapter = new VoltageAdapter(new Voltage220V());
        phone.charging(voltageAdapter);
    }
}

7. 桥接模式

桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立变化。
它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式
Bridge模式基于类的最小设计原则,通过使用封装、继承、及聚合等行为让不同的类履行不同的职责。
它主要特点是把抽象(Abstraction)和行为实现(Implementation)分离开来,从而可以保持各部分的独立性和已经应对它们的功能扩展
public interface IPhone {
    void open();
    void music();
    void close();
}

public class FoldedPhone implements IPhone {
    @Override
    public void open() {
        System.out.println("折叠手机开机");
    }

    @Override
    public void music() {
        System.out.println("折叠手机播放音乐");
    }

    @Override
    public void close() {
        System.out.println("折叠手机关机");
    }
}
public abstract class BaseBrand {
    private IPhone iPhone;

    public BaseBrand(IPhone iPhone) {
        this.iPhone = iPhone;
    }

    protected void open() {
        iPhone.open();
    }

    protected void music() {
        iPhone.music();
    }
    protected void close() {
        iPhone.close();
    }
}
public class Xiaomi extends BaseBrand {
    public Xiaomi(IPhone iPhone) {
        super(iPhone);
    }

    @Override
    public void open() {
        System.out.print("小米");
        super.open();
    }

    @Override
    public void music() {
        System.out.print("小米");
        super.music();
    }

    @Override
    public void close() {
        System.out.print("小米");
        super.close();
    }
}
public class TestBridge {
    public static void main(String[] args) {
        BaseBrand xiaomi = new Xiaomi(new FoldedPhone());
        xiaomi.open();
        xiaomi.music();
        xiaomi.close();
    }
}

8. 装饰者模式

一杯茶饮,可以往里添加东西,基调是茶(被装饰者)三选一,添加品(装饰者)可以无限添加,论怎么组合

8.1 Demo

在这里插入图片描述

public abstract class Drink {
    private float price = 0.0f;
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    public abstract float cost();
}

public class Tea extends Drink {
    @Override
    public float cost() {
        return super.getPrice();
    }
}
public class BlackTea extends Tea {
    public BlackTea() {
        setName("红茶");
        setPrice(3.0f);
    }
}
public class GreenTea extends Tea {
    public GreenTea() {
        setName("绿茶");
        setPrice(4.0f);
    }
}
public class WhiteTea extends Tea{
    public WhiteTea() {
        setName("白茶");
        setPrice(4.0f);
    }
}
public class Decorator extends Drink{

    private Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    public float cost() {
        return getPrice() + drink.cost();
    }

    @Override
    public String getName() {
        return super.getName() + "-" + super.getPrice() + " && " + drink.getName();
    }

}

public class Milk extends Decorator {
    public Milk(Drink drink) {
        super(drink);
        setName("牛奶");
        setPrice(2.0f);
    }
}

public class Pearl extends Decorator {

    public Pearl(Drink drink) {
        super(drink);
        setName("珍珠");
        setPrice(1.5f);
    }
}
public class Taro extends Decorator {
    public Taro(Drink drink) {
        super(drink);
        setName("芋圆");
        setPrice(2.5f);
    }
}
public class TestDecorator {
    public static void main(String[] args) {
        Drink order = new GreenTea();
        order = new Milk(order);
        System.out.println(order.getName());
        System.out.println(order.cost());
        
        order = new Pearl(order);
        System.out.println(order.getName());
        System.out.println(order.cost());

        order = new Taro(order);
        System.out.println(order.getName());
        System.out.println(order.cost());

    }
}

8.2 实例:JDK IO 的 InputStream

9. 组合模式

组合模式,又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树形结构已表示“整体-部分”的层次关系
需要遍历组织机构或者处理的对象具有属性结构时非常适合组合模式
需要对象有较高的抽象性,如果叶子和节点的差异性很大,比如有很多方法和属性都不一样时就不适合使用
例子:专业→学院→学校 共同点都是组织可以抽象,专业没有下一级是叶子,大学和学院是节点
package composite;
public abstract class Organization {
    private String name;
    private String des;

    public Organization(String name, String des) {
        this.name = name;
        this.des = des;
    }

    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 void add(Organization organization) {
        throw new UnsupportedOperationException();
    }
    protected void remove(Organization organization) {
        throw new UnsupportedOperationException();
    }
    public abstract void print();
}

package composite;

import java.util.ArrayList;
import java.util.List;
public class University extends Organization {
    List<Organization> organizations;
    public University(String name, String des) {
        super(name, des);
        this.organizations = new ArrayList<>();
    }

    @Override
    protected void add(Organization organization) {
        organizations.add(organization);
    }

    @Override
    protected void remove(Organization organization) {
        organizations.remove(organization);
    }

    @Override
    public void print() {
        System.out.println("--------" + getName() + "--------");
        organizations.forEach(Organization::print);
    }
}

package composite;

import java.util.ArrayList;
import java.util.List;
public class College extends Organization {
    List<Organization> organizations;
    public College(String name, String des) {
        super(name, des);
        this.organizations = new ArrayList<>();
    }

    @Override
    protected void add(Organization organization) {
        organizations.add(organization);
    }

    @Override
    protected void remove(Organization organization) {
        organizations.remove(organization);
    }

    @Override
    public void print() {
        System.out.println("--------" + getName() + "--------");
        organizations.forEach(Organization::print);
    }
}
public class Major extends Organization {
    public Major(String name, String des) {
        super(name, des);
    }

    @Override
    public void print() {
        System.out.println(getName());
    }
}
public class TestComposite {
    public static void main(String[] args) {
        University university = new University("北京大学", "Peking University");
        College college1 = new College("工商管理学院", "College of Business Administration");
        Major major1 = new Major("电子商务", "Electronic Commerce");
        Major major2 = new Major("旅游管理", "Tourism Management");
        college1.add(major1);
        college1.add(major2);
        College college2 = new College("计算机学院", "College of Computing");
        Major major3 = new Major("软件工程", "Software Engineering");
        Major major4 = new Major("网络工程", "Network Engineering");
        college2.add(major3);
        college2.add(major4);
        university.add(college1);
        university.add(college2);
        university.print();
    }
}

10. 外观模式

外观模式,也叫过程模式:外观模式为子系统的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用
外观模式通过定义一个一致的接口,用以屏蔽子系统内部的细节

11. 享元模式

1)享元模式(Flyweight Pattern)也叫蝇量模式:运用共享技术有效地支持大量细粒度对象
2)常用于系统底层开发,解决系统的性能问题,例如数据库连接池,里面都是创建好的连接对象,
	在这些连接对象中有我们需要的则直接拿来使用避免重新创建,没有则需要重新创建一个
3)享元模式能够解决重复对象的内存浪费问题,当系统中有大量相似对象需要缓冲池时,不需要重新创建对象,直接从缓冲池拿
4)经典应用场景池技术,例如String常量池、数据库连接池
内部状态:对象共享出来的信息,存储在享元对象内部不随环境改变而改变
外部状态:指对象得已依赖的一个标记,随环境改变而改变,是不可共享的状态
public abstract class BaseWebsite {
    /**
     * 内部状态
     */
    private String type;

    public String getType() {
        return type;
    }

    public BaseWebsite(String type) {
        this.type = type;
    }

    /**
     * @param userInfo 外部状态
     */
    public abstract void use(UserInfo userInfo);
}
public class ConcreteWebsite extends BaseWebsite {
    public ConcreteWebsite(String type) {
        super(type);
    }

    @Override
    public void use(UserInfo userInfo) {
        System.out.println(userInfo.getName() +  " 正在使用网站 " + getType());
    }
}
public class UserInfo {
    private String name;

    public UserInfo(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class WebsiteFactory {
    private static Map<String, BaseWebsite> cache = new HashMap<>();

    public static BaseWebsite getWebsite(String type) {
        BaseWebsite website = cache.get(type);
        if (null == website) {
            website = new ConcreteWebsite(type);
            cache.put(type,website);
        }
        return website;
    }

    public static void countWebsite(){
        System.out.println("网站个数:" + cache.size());
        if (cache.size() > 0) {
            cache.keySet().forEach(System.out::println);
        }
    }
}
public class TestFlyWeight {
    public static void main(String[] args) {
        BaseWebsite news = WebsiteFactory.getWebsite("NEWS");
        news.use(new UserInfo("Tom"));
        BaseWebsite blog = WebsiteFactory.getWebsite("BLOG");
        blog.use(new UserInfo("Mike"));
        BaseWebsite news1 = WebsiteFactory.getWebsite("NEWS");
        news1.use(new UserInfo("Jane"));
        BaseWebsite sports = WebsiteFactory.getWebsite("SPORTS");
        sports.use(new UserInfo("Maria"));
        WebsiteFactory.countWebsite();
    }
}

12. 代理模式

为一个对象提供一个替身,以控制对这个对象的访问,即通过代理对象访问目标对象
这样做的好处是可以在目标对象实现的基础上,额外增强功能操作,即扩展目标对象的功能

12.1 静态代理

手动创建一个代理对象
package proxy;

public class StaticProxy {
    public static void main(String[] args) {
        WeddingCompany weddingCompany = new WeddingCompany(new ManAndWife());
        weddingCompany.wedding();
    }
}

interface Marry {
    void wedding();
}

/**
 * 目标对象
 */
class ManAndWife implements Marry {

    @Override
    public void wedding() {
        System.out.println("新郎新娘闪亮登场……");
    }
}

/**
 * 代理对象
 */
class WeddingCompany implements Marry {

    private Marry marry;

    public WeddingCompany(Marry marry) {
        this.marry = marry;
    }

    @Override
    public void wedding() {
        prepare();
        marry.wedding();
        happyEnding();
    }

    private void prepare() {
        System.out.println("婚前准备……");
    }

    private void happyEnding() {
        System.out.println("完结撒花……");
    }
}

12.2 动态代理

通过反射动态地获得一个代理对象
package proxy;

import java.lang.reflect.Proxy;

public class DynamicProxyFactory {
    private Marry target;

    public DynamicProxyFactory(Marry target) {
        this.target = target;
    }

    public Object getProxy() {
        /*
        * loader 目标对象类加载器
        * interfaces 代理类要实现的接口列表
        * InvocationHandler 一个函数式接口,也就是要执行的代理方法的具体实现
        * */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), (proxy, method, args) -> {
            System.out.println("#动态代理#婚前准备……");
            //调用目标对象的方法
            Object result = method.invoke(target, args);
            System.out.println("#动态代理#完结撒花……");
            return result;
        });
    }
}

public class TestProxy {
    public static void main(String[] args) {
        Marry marry = new ManAndWife();
        DynamicProxyFactory factory = new DynamicProxyFactory(marry);
        Marry proxy = (Marry)factory.getProxy();
        proxy.wedding();
    }
}

12.3 Cglib代理

静态代理和动态代理都要求目标对象实现一个接口,但有时候目标对象只是一个单独的对象没有实现任何接口,
这个时候可以用目标对象子类来实现代理,也就是Cglib代理
它被广泛地运用于AOP框架,如Spring AOP
Cglib包的底层是通过字节码处理框架ASM来转换字节码并生成新的类
使用Cglib代理时目标对象不能时final类,static/final修饰的方法也不会被拦截
		<dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
public class Wedding {
    public void wedding() {
        System.out.println("婚礼进行时……");
    }
}
package proxy.cglibproxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class ProxyFactory implements MethodInterceptor {
    private  Object target;

    public ProxyFactory(Object 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();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("#Cglib代理#婚前准备……");
        Object result = method.invoke(target, objects);
        System.out.println("#Cglib代理#完结撒花……");

        return result;
    }
}

public class TestCglib {
    public static void main(String[] args) {
        Wedding wedding = new Wedding();
        ProxyFactory proxyFactory = new ProxyFactory(wedding);
        Wedding proxyInstance = (Wedding)proxyFactory.getProxyInstance();
        proxyInstance.wedding();
    }
}

13. 模板方法模式

模板方法模式(Template Method Pattern),在一个抽象类公开定义了执行它的方法模板,它的子类可以按需要重写方法实现,
但调用将以抽象类中定义的方法进行
简单来说,定义一个操作中的算法骨架,将一些步骤延迟到字类中,使得子类可以不改变一个算法的结构,就可以定义算法的一些特定步骤
钩子方法:定义一个空的方法,子类视情况看要不要重写实现
public abstract class Computer {
	/**
     * 模板方法一般都会加上final修饰防止子类重写
     */
    public final void buildUp() {
        cpu();
        disk();
        ram();
        fan();
        graphicsCard();
    }

    protected abstract void cpu();
    protected abstract void disk();
    protected abstract void ram();
    private void fan() {
        System.out.print(" 九州风神 ");
    }
    protected abstract void graphicsCard();
}
package template;

public class HightConfig extends Computer {
    @Override
    protected void cpu() {
        System.out.print("i7 9400H ");
    }

    @Override
    protected void disk() {
        System.out.print(" 1T ");
    }

    @Override
    protected void ram() {
        System.out.print(" 32G ");
    }

    @Override
    protected void graphicsCard() {
        System.out.println(" RTX 4080 ");
    }
}

package template;
public class LowConfig extends Computer {
    @Override
    protected void cpu() {
        System.out.print("i3 1200 ");
    }

    @Override
    protected void disk() {
        System.out.print(" 512G ");
    }

    @Override
    protected void ram() {
        System.out.print(" 8G ");
    }

    @Override
    protected void graphicsCard() {
        System.out.println(" GTX 1060 ");
    }
}

public class TestTemplate {
    public static void main(String[] args) {
        Computer highConfig = new HightConfig();
        highConfig.buildUp();
        Computer lowConfig = new LowConfig();
        lowConfig.buildUp();
    }
}

实例 :spring IOC

在这里插入图片描述

14. 命令模式

在软件设计中我们经常需要向某些对象发送请求,但是不知道请求的接收者是谁,也不知道被请求的操作是哪个
我们只需要在程序运行时指定请求的接收者即可,此时就可以用命令模式来进行设计
命令模式使得请求接收者和请求发送者解除耦合,让对象之间的调用关系更加灵活,实现解耦
在命令模式中会将一个请求封装为一个对象,以便使用不同的参数来表示不同的请求(即命名),同时命令模式也支持可撤销的操作
package command;

/**
 * @program: design-patterns
 * @description: 命令模板
 **/
public interface Command {
    /**
     * 执行
     */
    void execute();

    /**
     * 撤销
     */
    void revoke();
}

package command;
public class LightOnCommand implements Command {
    private LightReceiver lightReceiver;

    public LightOnCommand(LightReceiver lightReceiver) {
        this.lightReceiver = lightReceiver;
    }

    /**
     * 执行
     */
    @Override
    public void execute() {
        lightReceiver.on();
    }

    /**
     * 撤销
     */
    @Override
    public void revoke() {
        lightReceiver.off();
    }
}

package command;
public class LightOffCommand implements Command{
    private LightReceiver lightReceiver;

    public LightOffCommand(LightReceiver lightReceiver) {
        this.lightReceiver = lightReceiver;
    }
    /**
     * 执行
     */
    @Override
    public void execute() {
        lightReceiver.off();
    }

    /**
     * 撤销
     */
    @Override
    public void revoke() {
        lightReceiver.on();
    }
}

public class LightReceiver {
    public void  on() {
        System.out.println("打开电灯……");
    }

    public void  off() {
        System.out.println("关闭电灯……");
    }
}
package command;
public class RemoteController {
    Command[] onCommand;
    Command[] offCommand;
    Command revokeCommand;

    /**
     * 构建一个默认的遥控器
     */
    public RemoteController() {
        onCommand = new Command[5];
        offCommand = new Command[5];
        for (int i = 0; i < onCommand.length;i++) {
        // NonCommand空实现
            onCommand[i] = new NonCommand();
            offCommand[i] = new NonCommand();
        }
    }

    public void setCommand(int index, Command onCommand, Command offCommand) {
        this.onCommand[index] = onCommand;
        this.offCommand[index] = offCommand;
    }

    public void pushOnButton(int index) {
        this.onCommand[index].execute();
        revokeCommand = this.onCommand[index];
    }

    public void pushOffButton(int index) {
        this.offCommand[index].execute();
        revokeCommand = this.offCommand[index];
    }

    public void pushRevokeButton() {
        revokeCommand.revoke();
    }

}

public class TestCommand {
    public static void main(String[] args) {
        LightReceiver lightReceiver = new LightReceiver();
        Command lightOnCommand = new LightOnCommand(lightReceiver);
        Command lightOffCommand = new LightOffCommand(lightReceiver);
        RemoteController remoteController = new RemoteController();
        remoteController.setCommand(0,lightOnCommand,lightOffCommand);
        remoteController.pushOffButton(0);
        remoteController.pushOnButton(0);

        remoteController.pushRevokeButton();
    }
}

15. 访问者模式

封装一些作用于某种数据结构的各元素的操作,它可以在不改变数据结构的前提下,定义作用于这些元素的新的操作
基本工作原理:在被访问的类里面对外提供一个接待访问者的接口
运用场景:需要对一个对象结构中的元素进行很多不同的操作(这些操作互不关联),同时要避免这些操作污染对象本身
适用于数据结构的元素比较固定的场景
如下例子:有一个电脑组装,电脑的配件有 CPU、硬盘、内存条,针对不同的顾客群体有不同的折扣
如果再新增一个主板配件(元素)所有的visitor都得同步实现该配件的visit方法,同理再加一个机箱配件等等……
如果元素频繁变动对应的visitor也会频繁修改,所有适合元素固定的场景
package visitor;

import java.math.BigDecimal;

/**
 * @program: design-patterns
 * @description: 零件 (元素)
 * @create: 2022-08-30 21:14
 **/
public abstract class Components {
    private BigDecimal prise;

    public BigDecimal getPrise() {
        return prise;
    }

    public Components(BigDecimal prise) {
        this.prise = prise;
    }

    /**
     * 每个部件都要实现访问方法
     * @param visistor
     * @return
     */
    protected abstract BigDecimal visit(BaseVisistor visistor);

}
class Cpu extends Components{

    public Cpu(BigDecimal prise) {
        super(prise);
    }

    @Override
    public BigDecimal visit(BaseVisistor visistor) {
        return visistor.calculateCpu(this);
    }
}

class Disk extends Components{

    public Disk(BigDecimal prise) {
        super(prise);
    }
    @Override
    public BigDecimal visit(BaseVisistor visistor) {
        return visistor.calculateDisk(this);
    }
}

class Ram extends Components {
    public Ram(BigDecimal prise) {
        super(prise);
    }
    @Override
    public BigDecimal visit(BaseVisistor visistor) {
        return visistor.calculateRam(this);
    }
}
package visitor;

import java.math.BigDecimal;

/**
 * @program: design-patterns
 * @description: 外层对象
 * @create: 2022-08-30 21:13
 **/

public class Computer {
// 有些教程是直接把组件放到数组里面,访问的时候直接遍历数组
    private Components cpu;
    private Components disk;
    private Components ram;

    public Computer() {
        this.cpu = new Cpu(BigDecimal.valueOf(1200.00));
        this.disk = new Disk(BigDecimal.valueOf(600.00));
        this.ram = new Ram(BigDecimal.valueOf(500.00));
    }

    public BigDecimal accept(BaseVisistor visistor) {
        BigDecimal cost = BigDecimal.ZERO;
        cost = cost.add(this.cpu.visit(visistor));
        cost = cost.add(this.disk.visit(visistor));
        cost = cost.add(this.ram.visit(visistor));

        return cost;
    }
}
public interface BaseVisistor {

    /**
     * 计算CPU价格
     * @param cpu 考虑到要计算的目标很明确就是要CPU 所以这里没有用 Components去接收参数,其他同理
     * @return
     */
    BigDecimal calculateCpu(Cpu cpu);

    /**
     * 计算磁盘价格
     * @param disk
     * @return
     */
    BigDecimal calculateDisk(Disk disk);

    /**
     * 计算内存条价格
     * @param ram
     * @return
     */
    BigDecimal calculateRam(Ram ram);
}
public class StudentVisitor implements BaseVisistor {

    @Override
    public BigDecimal calculateCpu(Cpu cpu) {
        BigDecimal result = cpu.getPrise().multiply(BigDecimal.valueOf(0.70));
        System.out.println("学生计算CPU价格:" + result.toString());
        return result;
    }

    @Override
    public BigDecimal calculateDisk(Disk disk) {
        BigDecimal result = disk.getPrise().multiply(BigDecimal.valueOf(0.80));
        System.out.println("学生计算硬盘价格:" + result.toString());
        return result;
    }

    @Override
    public BigDecimal calculateRam(Ram ram) {
        BigDecimal result = ram.getPrise().multiply(BigDecimal.valueOf(0.90));
        System.out.println("学生计算内存条价格:" + result.toString());
        return result;
    }
}
public class StaffVisitor implements BaseVisistor {

    @Override
    public BigDecimal calculateCpu(Cpu cpu) {
        BigDecimal result = cpu.getPrise().multiply(BigDecimal.valueOf(0.75));
        System.out.println("员工计算CPU价格:" + result.toString());
        return result;
    }


    @Override
    public BigDecimal calculateDisk(Disk disk) {
        BigDecimal result = disk.getPrise().multiply(BigDecimal.valueOf(0.85));
        System.out.println("员工计算硬盘价格:" + result.toString());
        return result;
    }

    @Override
    public BigDecimal calculateRam(Ram ram) {
        BigDecimal result = ram.getPrise().multiply(BigDecimal.valueOf(0.90));
        System.out.println("员工计算内存条价格:" + result.toString());
        return result;
    }
}
public class CompanyVisitor implements BaseVisistor {

    @Override
    public BigDecimal calculateCpu(Cpu cpu) {
        BigDecimal result = cpu.getPrise().multiply(BigDecimal.valueOf(0.70));
        System.out.println("企业计算CPU价格:" + result.toString());
        return result;
    }

    @Override
    public BigDecimal calculateDisk(Disk disk) {
        BigDecimal result = disk.getPrise().multiply(BigDecimal.valueOf(0.70));
        System.out.println("企业计算硬盘价格:" + result.toString());
        return result;
    }

    @Override
    public BigDecimal calculateRam(Ram ram) {
        BigDecimal result = ram.getPrise().multiply(BigDecimal.valueOf(0.70));
        System.out.println("企业计算内存条价格:" + result.toString());
        return result;
    }
}
public class TestVisitor {
    public static void main(String[] args) {
        Computer computer = new Computer();
        StudentVisitor studentVisitor = new StudentVisitor();

        System.out.println("总价:" + computer.accept(studentVisitor).toString());
        System.out.println("-------------------------------");
        StaffVisitor staffVisitor = new StaffVisitor();
        System.out.println("总价:" + computer.accept(staffVisitor).toString());
        System.out.println("-------------------------------");
        CompanyVisitor companyVisitor = new CompanyVisitor();
        System.out.println("总价:" + computer.accept(companyVisitor).toString());

    }
}

16. 迭代器模式

提供一个迭代器用于遍历数据结构的元素
实现Iterator接口
public class Department {
    private String name;

    public Department(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
public class InfoCollegeIterator implements Iterator<Department> {

    private Department[] departments;
    private int index = 0;

    public InfoCollegeIterator(Department[] departments) {
        this.departments = departments;
    }

    @Override
    public boolean hasNext() {
        if (index > departments.length-1 || departments[index] == null) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public Department next() {
        Department department = this.departments[index];
        if (null == department) {
            throw new NoSuchElementException();
        } else {
            index++;
            return department;
        }
    }
}
public class InfoCollege {
    private String name;
    private Department[] departments;

    public String getName() {
        return name;
    }

    public InfoCollege() {
        this.name = "======信息学院======";
        departments = new Department[5];
        departments[0] = new Department("信息学院专业1");
        departments[1] = new Department("信息学院专业2");
        departments[2] = new Department("信息学院专业3");
        departments[3] = new Department("信息学院专业4");
        departments[4] = new Department("信息学院专业5");
    }

    public Iterator<Department> iterator() {
        return new InfoCollegeIterator(departments);
    }
}
public class TestItertor {
    public static void main(String[] args) {
        InfoCollege infoCollege = new InfoCollege();
        System.out.println(infoCollege.getName());
        Iterator<Department> iterator = infoCollege.iterator();
        while (iterator.hasNext()) {
            Department next = iterator.next();
            System.out.println(next.getName());
        }
    }
}

17. 观察者模式

当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。
JAVA 中已经有了对观察者模式的支持类 java.util.Observable  java.util.Observer
public interface Observer {
    void update(float temperature, String airQuality);
}
public class BaiduObserver implements Observer {

    @Override
    public void update(float temperature, String airQuality) {
        System.out.println("====百度天气====");
        System.out.println("温度:" + temperature);
        System.out.println("空气质量:" + airQuality);
    }
}
public class SinaObserver implements Observer {
    @Override
    public void update(float temperature, String airQuality) {
        System.out.println("====新浪天气====");
        System.out.println("温度:" + temperature);
        System.out.println("空气质量:" + airQuality);
    }
}
public class TencentObserver  implements Observer {
    @Override
    public void update(float temperature, String airQuality) {
        System.out.println("====腾讯天气====");
        System.out.println("温度:" + temperature);
        System.out.println("空气质量:" + airQuality);
    }
}
public class WeatherStation {
    List<Observer> observers;
    private float temperature;
    private String airQuality;

    public WeatherStation() {
        observers = new ArrayList<Observer>();
        temperature = 0f;
        airQuality = "";
    }

    public void register(Observer observer) {
        observers.add(observer);
    }
    public void remove(Observer observer) {
        if (observers.contains(observer)) {
            observers.remove(observer);
        }
    }
    public void weatherChange(float temperature, String airQuality) {
        this.temperature = temperature;
        this.airQuality = airQuality;
        notifyAllObservers();
    }
    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update(this.temperature,this.airQuality);

        }
    }
}
public class TestObserver {
    public static void main(String[] args) {
        WeatherStation weatherStation = new WeatherStation();
        weatherStation.register(new BaiduObserver());
        weatherStation.register(new SinaObserver());
        weatherStation.register(new TencentObserver());
        weatherStation.weatherChange(30f,"excellent");
    }
}

18. 中介者模式

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
当多个类互相耦合形成网状结构,使用中介者来变成星状结构
public abstract class Colleague {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 发送消息
     * @param name 发送给谁
     * @param msg 消息内容
     */
    protected abstract void sendMsg(String name, String msg);

    /**
     * 接收消息
     * @param msg 消息内容
     */
    protected abstract void getMsg(String msg);
}
public interface Mediator {

    void getMsg(String name, String msg);

    void register(Colleague colleague);
}
//中介
public class Wechat implements Mediator {

    private Map<String, Colleague> colleagueMap;

    @Override
    public void register(Colleague colleague) {
        colleagueMap.put(colleague.getName(),colleague);
    }

    public Wechat() {
        colleagueMap = new HashMap<>();
    }

    @Override
    public void getMsg(String name, String msg) {
        Colleague colleague = colleagueMap.get(name);
        if (colleague == null) {
            throw new NoSuchElementException();
        }
        colleague.getMsg(msg);
    }
}
public class XiaoMing extends Colleague {


    private Mediator mediator;

    public XiaoMing(Mediator mediator) {
        this.mediator = mediator;
        setName("小明");
        mediator.register(this);
    }

    @Override
    public void sendMsg(String name, String msg) {
        mediator.getMsg(name,msg);
    }

    @Override
    public void getMsg(String msg) {
        System.out.println(getName() + " 接收到消息:" + msg);
    }
}
public class XiaoHong extends Colleague {

    private Mediator mediator;

    public XiaoHong(Mediator mediator) {
        this.mediator = mediator;
        setName("小红");
        mediator.register(this);
    }

    @Override
    public void sendMsg(String name, String msg) {
        mediator.getMsg(name,msg);
    }

    @Override
    public void getMsg(String msg) {
        System.out.println(getName() + " 接收到消息:" + msg);
    }
}
public class TestMediator {
    public static void main(String[] args) {
        Wechat wechat = new Wechat();
        XiaoMing xiaoMing = new XiaoMing(wechat);
        XiaoHong xiaoHong = new XiaoHong(wechat);
        xiaoMing.sendMsg("小红","这周日你有空吗!");
        xiaoHong.sendMsg("小明","没空,滚!");
    }
}

19. 备忘录模式

备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象。
public class GameRole {
    private int hp;
    private int mp;

    public GameRole(int hp, int mp) {
        this.hp = hp;
        this.mp = mp;
    }

    public Memento saveStateToMemento() {
        return new Memento(this.hp,this.mp);
    }
    public void getStateFromMemento(Memento memento) {
        this.hp = memento.getHp();
        this.mp = memento.getMp();
    }
    
    public void setHp(int hp) {
        this.hp = hp;
    }

    public void setMp(int mp) {
        this.mp = mp;
    }

    @Override
    public String toString() {
        return "GameRole{" +
                "hp=" + hp +
                ", mp=" + mp +
                '}';
    }
}
public class Memento {
    private int hp;
    private int mp;

    public Memento(int hp, int mp) {
        this.hp = hp;
        this.mp = mp;
    }

    public int getHp() {
        return hp;
    }

    public int getMp() {
        return mp;
    }
}
public class CareTaker {

    /**
     * 只保存一次
     */
//    private Memento memento;
    /**
     * 保存单个对象多个历史
     */
    private List<Memento> mementos;
    /**
     * 保存多个对象多个历史
     */
//    private Map<String, Memento> mementoMap;

    public CareTaker() {
        mementos = new ArrayList<>();
    }
    public void add(Memento memento) {
        mementos.add(memento);
    }

    public Memento get(int index) {
        if (index > mementos.size()-1 || index < 0) {
            throw new NoSuchElementException();
        }
        return mementos.get(index);
    }
}
public class TestMemento {
    public static void main(String[] args) {
        GameRole tom = new GameRole(100, 100);
        System.out.println("Tom初始状态:"+tom.toString());
        CareTaker careTaker = new CareTaker();
        careTaker.add(tom.saveStateToMemento());

        tom.setHp(90);
        tom.setMp(80);
        System.out.println("TOM打怪:"+tom.toString());
        careTaker.add(tom.saveStateToMemento());

        tom.setHp(70);
        tom.setMp(50);
        System.out.println("TOM打怪:"+tom.toString());
        careTaker.add(tom.saveStateToMemento());

        tom.getStateFromMemento(careTaker.get(1));
        System.out.println("Tom恢复:"+tom.toString());
    }
}

20. 解释器模式

21. 状态模式

在状态模式(State Pattern)中,类的行为是基于它的状态改变的。
在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象。
允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。
主要解决:对象的行为依赖于它的状态(属性),并且可以根据它的状态改变而改变它的相关行为。
何时使用:代码中包含大量与对象状态有关的条件语句。

策略模式和解释器模式的区别:https://www.runoob.com/w3cnote/state-vs-strategy.html

public abstract class State {
    /**
     * 投币
     */
    public abstract void insertQuarter();

    /**
     * 退币
     */
    public abstract void ejectQuarter();

    /**
     * 转动出糖曲轴
     */
    public abstract void turnCrank();

    /**
     * 发糖
     */
    public abstract void dispense();

    /**
     * 退还硬币
     */
    protected void returnQuarter() {
        System.out.println("退币……");
    }
}
public class NoQuarterState extends State {
    private GumballMachine gumballMachine;

    public NoQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
    
    @Override
    public void insertQuarter() {
        System.out.println("正在投币……");
        gumballMachine.setState(gumballMachine.hasQuarterState);
    }

    @Override
    public void ejectQuarter() {
        System.out.println("还未投币,无法退币……");
    }
    
    @Override
    public void turnCrank() {
        System.out.println("还未投币,请先投币……");
    }

    @Override
    public void dispense() {
        System.out.println("还未投币,请先投币……");
    }
}
public class HasQuarterState extends State {
    private GumballMachine gumballMachine;

    public HasQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }

    @Override
    public void insertQuarter() {
        System.out.println("已经投币,无需重复投币……");
    }

    @Override
    public void ejectQuarter() {
        returnQuarter();
        gumballMachine.setState(gumballMachine.noQuarterState);
    }

    @Override
    public void turnCrank() {
        System.out.println("正在转动出糖轴……");
        gumballMachine.setState(gumballMachine.soldState);
    }

    @Override
    public void dispense() {
        System.out.println("请先转动出糖轴……");
    }
}
public class SoldState extends State {
    private GumballMachine gumballMachine;

    public SoldState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }

    @Override
    public void insertQuarter() {
        System.out.println("已经投币,无需重复投币……");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("正在发放糖果,无法退币……");
    }

    @Override
    public void turnCrank() {
        System.out.println("已经转动出糖曲轴,无需重复操作……");
    }

    @Override
    public void dispense() {
        int count = gumballMachine.getCount();
        if (count>0){
            System.out.println("分发一颗糖果……");
            gumballMachine.setCount(--count);
            if (count>0) {
                gumballMachine.setState(gumballMachine.noQuarterState);
                return;
            }

        }
        System.out.println("糖果已售罄……");
        gumballMachine.setState(gumballMachine.soldOutState);
    }
}
public class SoldOutState extends State {
    @Override
    public void insertQuarter() {
        System.out.println("糖果已售罄……");
    }

    @Override
    public void ejectQuarter() {
        System.out.println("糖果已售罄……");
    }

    @Override
    public void turnCrank() {
        System.out.println("糖果已售罄……");
    }

    @Override
    public void dispense() {
        System.out.println("糖果已售罄……");
    }
}
public class GumballMachine {
    public State noQuarterState;
    public State hasQuarterState;
    public State soldState;
    public State soldOutState;
    private State state;

    private int count;

    public GumballMachine() {
        noQuarterState = new NoQuarterState(this);
        hasQuarterState = new HasQuarterState(this);
        soldState = new SoldState(this);
        soldOutState = new SoldOutState();
        state = noQuarterState;
        count = 10;
    }

    public void insertQuarter(){
        state.insertQuarter();
    }

    public void ejectQuarter(){
        state.ejectQuarter();
    }

    public void turnCrank(){
        state.turnCrank();
    }

    public void dispense(){
        state.dispense();
    }

    public void setState(State state) {
        this.state = state;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }
}
public class TestState {
    public static void main(String[] args) {
        GumballMachine gumballMachine = new GumballMachine();
        for (int i = 0; i < 10; i++) {
            gumballMachine.insertQuarter();
            gumballMachine.turnCrank();
            gumballMachine.dispense();
        }
    }
}

22. 策略模式

在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
经典案例:Arrays.sort(T[] a, Comparator<? super T> c)
符合合成复用原则
public interface FlyBehavior {
    void flying();
}

public class FlyWithWings implements FlyBehavior {
    @Override
    public void flying() {
        System.out.println("天使之翼,飞~~~~");
    }
}

public class FlyNoWay implements FlyBehavior {
    @Override
    public void flying() {
        System.out.println("超人不会飞~~~");
    }
}

public class FlyWithRocket implements FlyBehavior{

    @Override
    public void flying() {
        System.out.println("芜湖!起飞!!!");
    }
}
public interface QuackBehavior {
    void quack();
}

public class GaQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("嘎~嘎~嘎~");
    }
}

public class ZhiQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("吱~吱~吱~");
    }
}

public class YiQuack implements QuackBehavior {
    @Override
    public void quack() {
        System.out.println("咿呀~咿呀~哟~");
    }
}
public class Duck {
    private String name;
    private FlyBehavior flyBehavior;
    private QuackBehavior quackBehavior;

    public Duck(String name, FlyBehavior flyBehavior, QuackBehavior quackBehavior) {
        this.name = name;
        this.flyBehavior = flyBehavior;
        this.quackBehavior = quackBehavior;
    }

    public void display() {
        System.out.println("======" + name + "======");
        flyBehavior.flying();
        quackBehavior.quack();
    }
}
public class TestStrategy {
    public static void main(String[] args) {
        Duck kedaya = new Duck("可达鸭", new FlyNoWay(), new ZhiQuack());
        Duck xyz = new Duck("小鸭子", new FlyWithRocket(), new YiQuack());
        Duck lty = new Duck("绿头鸭", new FlyWithWings(), new GaQuack());
        kedaya.display();
        xyz.display();
        lty.display();
    }
}

23. 责任链模式

顾名思义,责任链模式(Chain of Responsibility Pattern)为请求创建了一个接收者对象的链。这种模式给予请求的类型,对请求的发送者和接收者进行解耦。
在这种模式中,通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推。
public abstract class BaseResponsibility {
    private BaseResponsibility next;
    private String name;

    public BaseResponsibility(String name) {
        this.name = name;
    }

    public void setNext(BaseResponsibility next) {
        this.next = next;
    }

    public BaseResponsibility getNext() {
        return next;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract void purchase(PurchaseRequest purchaseRequest);

}
public class Department extends BaseResponsibility {
    public Department(String name) {
        super(name);
    }

    @Override
    public void purchase(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 0f && purchaseRequest.getPrice() <= 3000f) {
            System.out.println(getName() + "处理了采购请求:" + purchaseRequest.toString());
        } else {
            getNext().purchase(purchaseRequest);
        }
    }
}
public class College extends BaseResponsibility {
    public College(String name) {
        super(name);
    }

    @Override
    public void purchase(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 3000f && purchaseRequest.getPrice() <= 10000f) {
            System.out.println(getName() + "处理了采购请求:" + purchaseRequest.toString());
        } else {
            getNext().purchase(purchaseRequest);
        }
    }
}
public class University extends BaseResponsibility {
    public University(String name) {
        super(name);
    }

    @Override
    public void purchase(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 30000f ) {
            System.out.println(getName() + "处理了采购请求:" + purchaseRequest.toString());
        } else {
            throw new UnsupportedOperationException();
        }
    }
}
public class PurchaseRequest {
    private int amount;
    private float price;
    private String name;

    public PurchaseRequest(int amount, float price, String name) {
        this.amount = amount;
        this.price = price;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public float getPrice() {
        return price;
    }
    
    @Override
    public String toString() {
        return "PurchaseRequest{" +
                "amount=" + amount +
                ", price=" + price +
                ", name='" + name + '\'' +
                '}';
    }
}

public class TestResponsibility {
    public static void main(String[] args) {
        PurchaseRequest request = new PurchaseRequest(10, 50000f, "办公电脑");
        Department department = new Department("王主任");
        College college = new College("张院长");
        University university = new University("陈校长");
        department.setNext(college);
        college.setNext(university);
        department.purchase(request);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值