JAVA设计模式

****************************************************************************************************************************************************************************

复制代码
1、设计模式概述
【1】前辈们对代码开发经验的总结,解决问题的套路。是用来提高代码可复用性、可读性、可维护性、健壮性、安全性的解决方案。
【2】GoF23-23种设计模式。设计模式的本质是面向对象设计原则的实际运用。封装、继承、多态。代码的复用性、扩展性。
【3】模式名称、问题、解决方案、效果。一种思维、一种态度、一种进步
【4】创建型模式:单列模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
       结构性模式:适配器模式、桥接模式、装饰模式、组合模式、外观模式,享元模式、代理模式。
       行为型模式:模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式。

****************************************************************************************************************************************************************************

复制代码
2、OOP七大原则
【1】开闭原则:对扩展开放,对修改关闭。里氏替换原则:子类可以扩展,但是不要覆盖父类的东西。依赖倒置原则:面向接口编程。单一职责原则:一个类不要太复杂,原子性。
         接口隔离原则:为各个类建立专用接口。迪米特法则:只与直接朋友交谈,不跟陌生人说话。合成复用原则:尽量使用组合或聚合,而少使用继承来实现,A类为B类成员变量+构造方法。

****************************************************************************************************************************************************************************

复制代码
3、单例模式
【1】上来就创建可能会浪费空间。懒汉式、饿汉式
package com.day.pojo;

// 饿汉方式
public class Hungry {

    // 直接创建对象
    private final static Hungry hungry = new Hungry();

    // 私有化构造方法
    private Hungry() {

    }

    public static Hungry getInstance() {
        return hungry;
    }
}
***************************************懒汉式
package com.day.pojo;

// 懒汉式 ;  单线程确实是可以的,但是多线程不行
public class LazyMan {

    private static LazyMan lazyMan;

    private LazyMan() {
        System.out.println(Thread.currentThread().getName());
    }

    public static LazyMan getInstance() {
        if (lazyMan == null) {
            lazyMan = new LazyMan();
        }
        return lazyMan;
    }
}
***************************************多线层会有10个被创建
package com.day;

import com.day.pojo.LazyMan;

public class DayApplication {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                LazyMan.getInstance();
            }).start();
        }
    }
}
****************************所以要加锁,双重检测锁,就解决了多线程下只会被new一次的问题
package com.day.pojo;

// 懒汉式 ;  单线程确实是可以的,但是多线程不行
public class LazyMan {

    private static LazyMan lazyMan;

    private LazyMan() {
        System.out.println(Thread.currentThread().getName());
    }

    public static LazyMan getInstance() {
        // 加锁
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}
********************************
package com.day.pojo;

// 懒汉式 ;  单线程确实是可以的,但是多线程不行
public class LazyMan {

    private volatile static LazyMan lazyMan; // 保证变量指向空间时,但是还没有调用构造方法的问题被解决

    private LazyMan() {
        System.out.println(Thread.currentThread().getName());
    }

    public static LazyMan getInstance() {
        // 加锁
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}
【2】静态内部类实现
package com.day;

import com.day.pojo.LazyMan;

import java.lang.reflect.Constructor;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 反射破坏了单例模式
        LazyMan instance = LazyMan.getInstance();
        Constructor<LazyMan> constructor = LazyMan.class.getDeclaredConstructor(null);
        constructor.setAccessible(true);
        LazyMan notValid = constructor.newInstance();
        // 这两个不同就是破坏了
        System.out.println(instance);
        System.out.println(notValid);
    }
}
******************************* 加保护机制
package com.day.pojo;

// 懒汉式 ;  单线程确实是可以的,但是多线程不行
public class LazyMan {

    private volatile static LazyMan lazyMan; // 保证变量指向空间时,但是还没有调用构造方法的问题被解决

    private LazyMan() {
        synchronized (LazyMan.class) {
            if (lazyMan != null) {
                throw new RuntimeException("不用试图反射破坏异常");
            }
        }
        System.out.println(Thread.currentThread().getName());
    }

    public static LazyMan getInstance() {
        // 加锁
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}
****************************万物归于简单   用flag监控只能监控一次
package com.day.pojo;

// 懒汉式 ;  单线程确实是可以的,但是多线程不行
public class LazyMan {

    private volatile static LazyMan lazyMan; // 保证变量指向空间时,但是还没有调用构造方法的问题被解决
    private static boolean myProtectFlag = true;

    private LazyMan() {
        synchronized (LazyMan.class) {
            if (lazyMan != null) {
                throw new RuntimeException("不用试图反射破坏异常");
            }
        }
        if (!myProtectFlag) {
            throw new RuntimeException("对象已经实例化一次,多次实例化非法");
        }
        myProtectFlag = false;
        System.out.println(Thread.currentThread().getName());
    }

    public static LazyMan getInstance() {
        // 加锁
        if (lazyMan == null) {
            synchronized (LazyMan.class) {
                if (lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }
}
***************************黑白之间的攻防战...
【3】枚举本身也是一个class类
javap -p EnumSingle.class 反编译class命令。工具包jad.exe
package com.day.pojo;

// 枚举
public enum EnumSingle {
    INSTANCE;

    public EnumSingle getInstance() {
        return INSTANCE;
    }
}
**************************枚举类基础知识。定义一组常量使用枚举类。可以当做单例模式的实现。
JDK1.5之前,用private final String seasonName="秋天";
package com.day.pojo;

public class MyBefore {
    private final String seasonName;
    private final String seasonDesc;

    private MyBefore(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }

    public static final MyBefore SPRING = new MyBefore("春天", "春暖花开");
    public static final MyBefore SUMMER = new MyBefore("夏天", "夏日炎炎");

    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }
}
**************************
package com.day;

import com.day.pojo.MyBefore;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        MyBefore spring = MyBefore.SPRING;
        System.out.println(spring.getSeasonName());
    }
}
*****************************JDK 1.5之后
package com.day.pojo;

public enum MyEnum {
    // 罗列枚举项
    SPRING("春天", "春暖花开"),
    SUMMER("夏天", "夏日炎炎");

    private final String seasonName;
    private final String seasonDesc;

    private MyEnum(String seasonName, String seasonDesc) {
        this.seasonName = seasonName;
        this.seasonDesc = seasonDesc;
    }


    public String getSeasonName() {
        return seasonName;
    }

    public String getSeasonDesc() {
        return seasonDesc;
    }
}
************************
package com.day;

import com.day.pojo.MyEnum;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        MyEnum SPRING = MyEnum.SPRING;
        System.out.println(SPRING.getSeasonName());
    }
}

****************************************************************************************************************************************************************************

复制代码
4、工厂模式
【1】不用new对象,简单工厂模式、工厂方法模式。满足的原则:开闭原则、依赖倒转原则、迪米特法则。调用者与实现类解耦。
package com.day.pojo;

public interface Car {
    void name();
}
**************************
package com.day.pojo;

public class ChinaCar implements Car {
    @Override
    public void name() {
        System.out.println("中国造的车...");
    }
}
**************************
package com.day.pojo;

public class AmericanCar implements Car {
    @Override
    public void name() {
        System.out.println("美国造的车...");
    }
}
**************************
package com.day.pojo;

// 静态工厂模式,如果不修改代码,不方便扩展
public class CarFactory {
    public static Car getCar(String car) {
        if (car.equals("中国")) {
            return new ChinaCar();
        } else if (car.equals("美国")) {
            return new AmericanCar();
        } else {
            return null;
        }
    }
}
**************************
package com.day;

import com.day.pojo.AmericanCar;
import com.day.pojo.Car;
import com.day.pojo.CarFactory;
import com.day.pojo.ChinaCar;

public class DayApplication {
    public static void main(String[] args) throws Exception {
      /*  Car chinaCar = new ChinaCar();
        Car americanCar = new AmericanCar();*/
        Car chinaCar = CarFactory.getCar("中国");
        Car americanCar = CarFactory.getCar("美国");
        chinaCar.name();
        americanCar.name();
    }
}
**************************
【2】感觉类变多了...多了一个车的工厂接口,每多一个车,就多一个车工厂实现车的工厂接口。结论:简单工厂更实用、简单

****************************************************************************************************************************************************************************

复制代码
5、抽象工厂模式
【1】生产工厂的工厂。根据不同的业务来写。对于稳定的业务,还是很强大的。

抽象工厂模式.zip

****************************************************************************************************************************************************************************

复制代码
6、建造者模式
【1】创建者模式:提供了创建对象的最佳方式。
package com.day.build;

// 抽象的建造者
public abstract class Builder {
    abstract void build_1();

    abstract void build_2();

    abstract void build_3();

    abstract void build_4();

    abstract Product getProduct();
}
**************************************
package com.day.build;

public class Worker extends Builder {

    private Product product;

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

    @Override
    void build_1() {
        product.setBuild_1("地基");
        System.out.println("地基建造完毕");
    }

    @Override
    void build_2() {
        product.setBuild_2("钢筋");
        System.out.println("钢筋建造完毕");
    }

    @Override
    void build_3() {
        product.setBuild_3("电线");
        System.out.println("电线建造完毕");
    }

    @Override
    void build_4() {
        product.setBuild_4("粉刷");
        System.out.println("粉刷完毕");
    }

    @Override
    Product getProduct() {
        return product;
    }
}
***********************************************
package com.day.build;

public class Product {
    private String build_1;
    private String build_2;
    private String build_3;
    private String build_4;

    @Override
    public String toString() {
        return "Product{" +
                "build_1='" + build_1 + ''' +
                ", build_2='" + build_2 + ''' +
                ", build_3='" + build_3 + ''' +
                ", build_4='" + build_4 + ''' +
                '}';
    }

    public String getBuild_1() {
        return build_1;
    }

    public void setBuild_1(String build_1) {
        this.build_1 = build_1;
    }

    public String getBuild_2() {
        return build_2;
    }

    public void setBuild_2(String build_2) {
        this.build_2 = build_2;
    }

    public String getBuild_3() {
        return build_3;
    }

    public void setBuild_3(String build_3) {
        this.build_3 = build_3;
    }

    public String getBuild_4() {
        return build_4;
    }

    public void setBuild_4(String build_4) {
        this.build_4 = build_4;
    }
}
*********************************
package com.day.build;

// 指挥
public class Director {
    public Product build(Builder builder) {
        builder.build_1();
        builder.build_2();
        builder.build_3();
        builder.build_4();
        return builder.getProduct();
    }
}
*******************************************
package com.day;

import com.day.build.Director;
import com.day.build.Product;
import com.day.build.Worker;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 指挥
        Director director = new Director();
        Product product = director.build(new Worker());
        System.out.println(product);
    }
}
【2】客户自己的搭配
package com.day.build;

// 抽象的建造者
public abstract class Builder {
    public abstract Builder build_1(String msg);

    public abstract Builder build_2(String msg);

    public abstract Builder build_3(String msg);

    public abstract Builder build_4(String msg);

    public abstract Product getProduct();
}
************************
package com.day.build;

public class Product {
    private String build_1 = "地基";
    private String build_2 = "钢筋";
    private String build_3 = "电线";
    private String build_4 = "粉刷";

    public String getBuild_1() {
        return build_1;
    }

    public void setBuild_1(String build_1) {
        this.build_1 = build_1;
    }

    public String getBuild_2() {
        return build_2;
    }

    public void setBuild_2(String build_2) {
        this.build_2 = build_2;
    }

    public String getBuild_3() {
        return build_3;
    }

    public void setBuild_3(String build_3) {
        this.build_3 = build_3;
    }

    public String getBuild_4() {
        return build_4;
    }

    public void setBuild_4(String build_4) {
        this.build_4 = build_4;
    }

    @Override
    public String toString() {
        return "Product{" +
                "build_1='" + build_1 + ''' +
                ", build_2='" + build_2 + ''' +
                ", build_3='" + build_3 + ''' +
                ", build_4='" + build_4 + ''' +
                '}';
    }
}
******************************
package com.day.build;

public class Worker extends Builder {

    private Product product;

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

    @Override
    public Builder build_1(String msg) {
        product.setBuild_1(msg);
        System.out.println(msg + "建造完毕");
        return this;
    }

    @Override
    public Builder build_2(String msg) {
        product.setBuild_2(msg);
        System.out.println(msg + "建造完毕");
        return this;
    }

    @Override
    public Builder build_3(String msg) {
        product.setBuild_3(msg);
        System.out.println(msg + "建造完毕");
        return this;
    }

    @Override
    public Builder build_4(String msg) {
        product.setBuild_4(msg);
        System.out.println(msg + "建造完毕");
        return this;
    }

    @Override
    public Product getProduct() {
        return product;
    }
}
*********************************
package com.day;

import com.day.build.Product;
import com.day.build.Worker;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 服务员
        Worker worker = new Worker();
        Product product = worker.build_1("可乐").build_2("鸡翅").getProduct();
        System.out.println(product);
    }
}

****************************************************************************************************************************************************************************

复制代码
7、原型模式
【1】克隆:Copy。实际中达到提效的目的。
package com.day.prototype;

import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

// 复制UP主。视频的类
@Data
@NoArgsConstructor // 无参构造
public class Video implements Cloneable {
    private String name;
    private Date createTime;

    // 有参构造
    public Video(String name, Date createTime) {
        this.name = name;
        this.createTime = createTime;
    }


    @Override
    public Object clone() throws CloneNotSupportedException {
        Object object = super.clone();
        Video video = (Video) object;
        // 克隆他的属性
        video.createTime = (Date) this.createTime.clone(); // 这个可以实现深克隆
        return object;
    }
}
**************************************
package com.day;


import com.day.prototype.Video;

import java.util.Date;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        Date date = new Date();
        Video video_1 = new Video("纠错大队长", date);
        System.out.println(video_1 + "---" + video_1.hashCode());
        // 克隆(浅克隆)
        Video video_2 = (Video) video_1.clone();
        // video_2 = video_1;
        // video_2.setName("内容审核");
        date.setTime(123456);
        System.out.println(video_1 + "---" + video_1.hashCode());
        System.out.println(video_2 + "---" + video_1.hashCode());
        // 深克隆
        // 修改代码后就不会时间改变都改变了
    }
}

****************************************************************************************************************************************************************************

复制代码
8、适配器模式
【1】创建式模式已经学完。现在开始结构型模式。
【2】USB网线转换器(适配器的思想)
package com.day.adapter;

import com.day.service.NetToUsb;

// 客户端类
public class Computer {
    public void net(NetToUsb netToUsb) {
        // 上网实现,找一个转接
        netToUsb.handleRequest();
    }
}
*************************
package com.day.adapter;

// 网线
public class Adapter {
    public void request() {
        System.out.println("连接网线上网...");
    }
}
******************************
package com.day.service;

public interface NetToUsb {
    // 处理请求
    public void handleRequest();
}
*******************************
package com.day.service.imp;

import com.day.adapter.Adapter;
import com.day.service.NetToUsb;

// 1 继承
// 2 组合
public class NetToUsbImp extends Adapter implements NetToUsb {
    @Override
    public void handleRequest() {
        super.request();
        System.out.println("可以上网了...");
    }
}
【3】使用组合的方式(单继承局限性太大了,优先使用组合的方式)
package com.day.service.imp;

import com.day.adapter.Adapter;
import com.day.service.NetToUsb;

// 1 继承
// 2 组合
public class NetToUsbImp implements NetToUsb {
    private Adapter adapter;

    public NetToUsbImp(Adapter adapter) {
        this.adapter = adapter;
    }

    @Override
    public void handleRequest() {
        adapter.request();
        System.out.println("可以上网了...");
    }
}
********************************
package com.day;

import com.day.adapter.Adapter;
import com.day.adapter.Computer;
import com.day.service.imp.NetToUsbImp;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 电脑 适配器 网线
        Computer computer = new Computer();
        Adapter adapter = new Adapter();
        NetToUsbImp netToUsbImp = new NetToUsbImp(adapter);// 这里就实现了组合 这是个最高效的方式
        computer.net(netToUsbImp);
    }
}

****************************************************************************************************************************************************************************

复制代码
9、桥接模式
【1】将抽象的部分与它的实现分离开。通过一座桥把他们连接起来
package com.day.service;

public interface Brand {
    void info();
}
*****************************
package com.day.service.imp;

import com.day.service.Brand;
import lombok.Data;

@Data
public class LenovoImp implements Brand {
    @Override
    public void info() {
        System.out.println("联想");
    }
}
*****************************
package com.day.service.imp;

import com.day.service.Brand;
import lombok.Data;

@Data
public class AppleImp implements Brand {

    @Override
    public void info() {
        System.out.println("苹果");
    }
}
*****************************
package com.day.service;

import lombok.Data;

@Data
public abstract class Computer {
    // 组合品牌
    protected Brand brand; // 这里是一座桥............................................................

    public Computer(Brand brand) {
        this.brand = brand;
    }

    public void computerInfo() {
        brand.info();
    }
}
*****************************
package com.day.service.imp;

import com.day.service.Brand;
import com.day.service.Computer;

public class Desktop extends Computer {
    public Desktop(Brand brand) {
        super(brand);
    }

    @Override
    public void computerInfo() {
        super.computerInfo();
        System.out.println("台式机");
    }
}
*****************************
package com.day.service.imp;

import com.day.service.Brand;
import com.day.service.Computer;

public class Laptop extends Computer {
    public Laptop(Brand brand) {
        super(brand);
    }

    @Override
    public void computerInfo() {
        super.computerInfo();
        System.out.println("笔记本");
    }
}
*****************************
package com.day;

import com.day.service.Brand;
import com.day.service.Computer;
import com.day.service.imp.AppleImp;
import com.day.service.imp.Desktop;
import com.day.service.imp.Laptop;
import com.day.service.imp.LenovoImp;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        Computer computer = new Laptop(new AppleImp());
        computer.computerInfo();
        Computer computer2 = new Desktop(new LenovoImp());
        computer2.computerInfo();
    }
}
【2】桥接模式优于多继承。里面会用到抽象类的(这里抽象类的用武之地)。

****************************************************************************************************************************************************************************

复制代码
10、静态代理模式
【1】中介。代理模式就是SpringAOP的底层。分类:静态代理、动态代理。
【2】抽象角色、真是角色、代理角色。代理后一般会做一些附属操作。
package com.day.service;

public interface Rent {
    public void rentHouse();
}
******************
package com.day.pojo;

import com.day.service.Rent;

// 房东
public class Host implements Rent {
    @Override
    public void rentHouse() {
        System.out.println("房东出租房子");
    }
}
******************
package com.day.pojo;

public class Client {

}
******************
package com.day.pojo;

import com.day.service.Rent;

// 代理
public class Proxy implements Rent {
    // 拿房东
    Host host;

    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rentHouse() {
        seeHouse();
        sign();
        fee();
        host.rentHouse();
    }

    // 看房
    public void seeHouse() {
        System.out.println("中介带你看房");
    }

    // 收中介费
    public void fee() {
        System.out.println("收中介费");
    }

    // 签合同
    public void sign() {
        System.out.println("签合同");
    }
}
**************************
package com.day;

import com.day.pojo.Host;
import com.day.pojo.Proxy;

public class DayApplication {
    public static void main(String[] args) throws Exception {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rentHouse();
    }
}
***********************
【3】代理的好处:可以使真是角色的操作更加纯粹。公共也就代理角色实现,实现了业务分工。公共业务发生扩展时方便集中管理。缺点:真是角色1V1代理类

****************************************************************************************************************************************************************************

复制代码
11、静态代理再次理解
【1】感觉真的很美妙...。保持原有的类不变。也就是AOP的实现机制。
package com.day.service;

public interface UserService {
    public void insert();

    public void delete();

    public void update();

    public void select();
}
*****************************
package com.day.service.imp;

import com.day.service.UserService;

// 真是对象
public class UserServiceImp implements UserService {
    @Override
    public void insert() {
        System.out.println("增加");
    }

    @Override
    public void delete() {
        System.out.println("删除");
    }

    @Override
    public void update() {
        System.out.println("修改");
    }

    @Override
    public void select() {
        System.out.println("查询");
    }
}
*****************************
package com.day.pojo;

import com.day.service.UserService;
import com.day.service.imp.UserServiceImp;

public class Proxy implements UserService {
    UserServiceImp userServiceImp;

    public Proxy(UserServiceImp userServiceImp) {
        this.userServiceImp = userServiceImp;
    }

    @Override
    public void insert() {
        log("add");
        userServiceImp.insert();
    }

    @Override
    public void delete() {
        log("delete");
        userServiceImp.delete();
    }

    @Override
    public void update() {
        log("update");
        userServiceImp.update();
    }

    @Override
    public void select() {
        log("select");
        userServiceImp.select();
    }

    // 日志方法
    public void log(String msg) {
        System.out.println(msg + "打印日志...");
    }
}
*****************************
package com.day;

import com.day.pojo.Proxy;
import com.day.service.UserService;
import com.day.service.imp.UserServiceImp;

// 需求 加日志
public class DayApplication {
    public static void main(String[] args) throws Exception {
        /*UserServiceImp userServiceImp = new UserServiceImp();
        userServiceImp.insert();*/
        UserServiceImp userServiceImp = new UserServiceImp();
        Proxy proxy = new Proxy(userServiceImp);
        proxy.insert();
        proxy.select();
    }
}

****************************************************************************************************************************************************************************

复制代码
12、动态代理
【1】代理1V1类导致代码很多,怎么处理呢。最核心的点:动态代理的代理类是动态生成的,不是我们直接写好的(利于的是反射技术)。
【2】基于接口的动态代理、基于类的动态代理、
package com.day.service;

public interface Rent {
    public void rent();
}
************************************
package com.day.pojo;

import com.day.service.Rent;

// 房东
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}
************************************
package com.day.pojo;

import com.day.service.Rent;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    // 被代理的接口
    private Rent rent;

    public ProxyInvocationHandler(Rent rent) {
        this.rent = rent;
    }

    // 生成得到代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
    }

    // 处理代理示例 并反馈结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 本质就是使用反射
        sign();
        Object object = method.invoke(rent, args);
        fee();
        return object;
    }

    public void fee() {
        System.out.println("收中介费");
    }

    public void sign() {
        System.out.println("签合同");
    }
}
************************************
package com.day;

import com.day.pojo.Host;
import com.day.pojo.ProxyInvocationHandler;
import com.day.service.Rent;

// 需求 加日志
public class DayApplication {
    public static void main(String[] args) throws Exception {
        Host host = new Host();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(host);
        Rent proxy = (Rent) proxyInvocationHandler.getProxy(); // proxy是动态生成的
        proxy.rent();
    }
}
*****************************************
【3】万能代理类。好处:动态代理代理的是一个接口,一般是一类业务,业务之间切换也很方便。
package com.day.pojo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
    // 被代理的接口
    private Object target;

    public ProxyInvocationHandler(Object target) {
        this.target = target;
    }

    // 生成得到代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    // 处理代理示例 并反馈结果
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 本质就是使用反射
        log(method.getName());
        sign();
        Object object = method.invoke(target, args);
        fee();
        return object;
    }

    public void fee() {
        System.out.println("收中介费");
    }

    public void sign() {
        System.out.println("签合同");
    }

    public void log(String msg) {
        System.out.println(msg + "打印日志...");
    }
}

****************************************************************************************************************************************************************************

复制代码
13、装饰者设计模式
【1】咖啡+调料,当增加咖啡种类、调料种类时,如果一一增加,则类的数量会爆炸。
【2】将每一种咖啡都拥有所有的调料,这样就可以随便匹配。更好的方案是使用装饰者模式。
【3】将新功能动态的附加到对象上。邮寄快递需要包装下。主体是咖啡,装饰者是调料。
【4】实际案例:Drink抽象类,ShortBlack单品咖啡,Decorator是一个装饰类(含有被装饰对象)。cost方法存在递归计算。
【5】这个在实际的商城中也可以用到价格叠加,卧槽。

装饰者模式.zip

****************************************************************************************************************************************************************************

复制代码
14、组合模式
【1】展示学校、学院、系。看成树结构,组合模式。
package com.day.service;

import lombok.Data;

@Data
public abstract class Organization {
    private String name;
    private String des;

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

    public abstract void print(); // 打印

    public void add(Organization organization) {
        // 默认实现
        throw new UnsupportedOperationException();
    }

    protected void remove(Organization organization) {
        // 默认实现
        throw new UnsupportedOperationException();
    }
}
********************************
package com.day.service.imp;

import com.day.service.Organization;

import java.util.ArrayList;
import java.util.List;

public class University extends Organization {
    List<Organization> organizationList = new ArrayList<>();

    // 构造器
    public University(String name, String des) {
        super(name, des);
    }

    @Override
    public void print() {
        System.out.println("----------" + getName() + "---------------" + getDes());
        for (Organization temp : organizationList) {
            temp.print();
        }
    }

    @Override
    public void add(Organization organization) {
        organizationList.add(organization);
    }

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

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }
}
********************************
package com.day.service.imp;

import com.day.service.Organization;

import java.util.ArrayList;
import java.util.List;

public class College extends Organization {
    List<Organization> organizationList = new ArrayList<>();

    // 构造器
    public College(String name, String des) {
        super(name, des);
    }

    @Override
    public void print() {
        System.out.println("----------" + getName() + "---------------" + getDes());
        for (Organization temp : organizationList) {
            temp.print();
        }
    }

    @Override
    public void add(Organization organization) {
        organizationList.add(organization);
    }

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

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }
}
********************************
package com.day.service.imp;

import com.day.service.Organization;

import java.util.ArrayList;
import java.util.List;

public class Department extends Organization {
    List<Organization> organizationList = new ArrayList<>();

    // 构造器
    public Department(String name, String des) {
        super(name, des);
    }

    @Override
    public void print() {
        System.out.println("----------" + getName() + "---------------" + getDes());
       /* for (Organization temp : organizationList) {
            temp.print();
        }*/
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }
}
********************************
package com.day;

import com.day.service.Organization;
import com.day.service.imp.College;
import com.day.service.imp.Department;
import com.day.service.imp.University;

// 需求 加日志
public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 从大到小
        Organization university = new University("哈工大", "东三省最牛批");
        Organization college = new College("计算机学院", "亚洲前四");
        Organization college_2 = new College("软件学院", "也很牛批");
        college.add(new Department("计算机专业1", "可以"));
        college.add(new Department("计算机专业2", "非常可以"));
        college.add(new Department("计算机专业3", "非常牛批"));
        college_2.add(new Department("软件专业1", "可以"));
        college_2.add(new Department("软件专业2", "非常可以"));
        college_2.add(new Department("软件专业3", "非常牛批"));
        university.add(college);
        university.add(college_2);
        university.print();
    }
}
【2】源码用到的组合模式:HashMap。接口类的总览很重要,面向接口编程。

****************************************************************************************************************************************************************************

复制代码
15、外观模式
【1】很多设备需要控制,太多的遥控器,所以你需要一个万能遥控器。
【2】外观模式也叫过程模式,给业务封装一个更高级的接口。感觉就是包装了下。
package com.day.service.imp;

public class DvdPlayer {
    // 单例模式
    private static DvdPlayer dvdPlayer = new DvdPlayer();

    public static DvdPlayer getInstance() {
        return dvdPlayer;
    }

    public void start() {
        System.out.println("DVD 打开");
    }

    public void stop() {
        System.out.println("DVD 关闭");
    }

    public void play() {
        System.out.println("DVD 播放");
    }
}
*************************************
package com.day.service.imp;

public class TvPlayer {
    // 单例模式
    private static TvPlayer tvPlayer = new TvPlayer();

    public static TvPlayer getInstance() {
        return tvPlayer;
    }

    public void start() {
        System.out.println("电视 打开");
    }

    public void stop() {
        System.out.println("电视 关闭");
    }

    public void play() {
        System.out.println("电视 播放");
    }
}
*************************************
package com.day.service.imp;

public class AirPlayer {
    // 单例模式
    private static AirPlayer airPlayer = new AirPlayer();

    public static AirPlayer getInstance() {
        return airPlayer;
    }

    public void start() {
        System.out.println("空调 打开");
    }

    public void stop() {
        System.out.println("空调 关闭");
    }

    public void play() {
        System.out.println("空调 播放");
    }
}
*************************************
package com.day;

import com.day.service.imp.AirPlayer;
import com.day.service.imp.DvdPlayer;
import com.day.service.imp.TvPlayer;

// 主函数入口
public class DayApplication {
    private AirPlayer airPlayer;
    private DvdPlayer dvdPlayer;
    private TvPlayer tvPlayer;

    public DayApplication() {
        super();
        this.airPlayer = AirPlayer.getInstance();
        this.tvPlayer = TvPlayer.getInstance();
        this.dvdPlayer = DvdPlayer.getInstance();
    }

    public static void main(String[] args) throws Exception {
        DayApplication dayApplication = new DayApplication();
        dayApplication.ready();
        dayApplication.play();
    }

    // 准备
    public void ready() {
        airPlayer.start();
        dvdPlayer.start();
        tvPlayer.start();
    }

    public void play() {
        airPlayer.play();
        dvdPlayer.play();
        tvPlayer.play();
    }
}

****************************************************************************************************************************************************************************

复制代码
16、享元模式
【1】就是有一份源代码,然后根据不同的需求修改。用共享模式支持大量细粒度的对象。棋子内部状态是颜色,坐标是外部状态。
package com.day.service;

import com.day.service.imp.User;

public abstract class WebSite {
    public abstract void use(User user);
}
****************************
package com.day.service.imp;

import com.day.service.WebSite;

public class ConcreteWebSite extends WebSite {
    private String type = "";// 网站发布形式

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

    @Override
    public void use(User user) {
        System.out.println(user.getName() + "网站的发布形式为:" + type);
    }
}
****************************
package com.day.service.imp;

import com.day.service.WebSite;

import java.util.HashMap;

// 工厂类
public class WebSiteFactory {
    // 集合 充当池子的作用
    private HashMap<String, ConcreteWebSite> hashMapPool = new HashMap<>();

    // 根据网站类型,返回网站。如果没有网站就创建,然后放入到池子中并返回
    public WebSite getWebSiteInstance(String type) {
        if (!hashMapPool.containsKey(type)) {
            // 没有就创建
            hashMapPool.put(type, new ConcreteWebSite(type));
        }
        return (WebSite) hashMapPool.get(type);
    }

    // 获取网站分类的总数
    public int getWebSiteNum() {
        return hashMapPool.size();
    }
}
****************************
package com.day;

import com.day.service.WebSite;
import com.day.service.imp.User;
import com.day.service.imp.WebSiteFactory;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        WebSiteFactory webSiteFactory = new WebSiteFactory();
        User user = new User();
        user.setName("陈翔");
        WebSite webSite = webSiteFactory.getWebSiteInstance("新闻");
        webSite.use(user);
        user.setName("蘑菇头");
        webSite = webSiteFactory.getWebSiteInstance("博客");
        webSite.use(user);
        webSite = webSiteFactory.getWebSiteInstance("博客");
        webSite.use(user);
        webSite = webSiteFactory.getWebSiteInstance("博客");
        webSite.use(user);
        System.out.println("网站分类一共 " + webSiteFactory.getWebSiteNum());
    }
}

****************************************************************************************************************************************************************************

复制代码
17、模板模式
【1】在抽象类中公开定义其他方法的模板。
package com.day.service;

// 抽象类
public abstract class SoybeanMilk {
    // 模板方法 用final修饰,不让子类覆盖
    public final void make() {
        select();
        addAnother();
        withWater();
        beat();
    }

    void select() {
        System.out.println("1 选择鲜豆");
    }

    public abstract void addAnother(); // 子类实现

    void withWater() {
        System.out.println("3 黄豆与配料开始浸泡 需要3小时");
    }

    void beat() {
        System.out.println("4 放到豆浆机打磨");
    }
}
*******************************************
package com.day.service.imp;

import com.day.service.SoybeanMilk;

public class RedBeanMilk extends SoybeanMilk {
    @Override
    public void addAnother() {
        System.out.println("2 加入好的红豆");
    }
}
*******************************************
package com.day.service.imp;

import com.day.service.SoybeanMilk;

public class BlackBeanMilk extends SoybeanMilk {
    @Override
    public void addAnother() {
        System.out.println("2 加入上号的芝麻");
    }
}
*******************************************
package com.day;

import com.day.service.imp.BlackBeanMilk;
import com.day.service.imp.RedBeanMilk;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        // 红豆
        RedBeanMilk redBeanMilk = new RedBeanMilk();
        redBeanMilk.make();
        System.out.println("-------------------------------------------------------");
        // 芝麻
        BlackBeanMilk blackBeanMilk = new BlackBeanMilk();
        blackBeanMilk.make();
    }
}

模板模式+钩子方法.zip

****************************************************************************************************************************************************************************

复制代码
18、命令模式
【1】面临的场景很像外观模式。还是万能遥控器。感觉写来写去都差不多了呢...卧槽
package com.day.service;

//命令接口
public interface Command {
    public void exe(); // 执行

    public void undo(); // 撤销操作
}
***************************************
package com.day.service.imp;

import com.day.service.Command;

public class LightOnCommand implements Command {
    LightReceiver lightReceiver;

    // 构造器接受实例
    public LightOnCommand(LightReceiver lightReceiver) {
        this.lightReceiver = lightReceiver;
    }

    @Override
    public void exe() {
        lightReceiver.on();
    }

    @Override
    public void undo() {
        lightReceiver.off();
    }
}
***********************************
package com.day.service.imp;

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

    public void off() {
        System.out.println("电灯 关闭");
    }
}
***********************************
package com.day;

import com.day.service.imp.LightOnCommand;
import com.day.service.imp.LightReceiver;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        LightReceiver lightReceiver = new LightReceiver();
        LightOnCommand lightOnCommand = new LightOnCommand(lightReceiver);
        lightOnCommand.exe();
        lightOnCommand.undo();
    }
}

****************************************************************************************************************************************************************************

复制代码
19、访问者模式
【1】在被访问类里,加一个对外提供接待访问者的接口。
【2】这里还是需要深度理解下的。

访问者模式.zip

****************************************************************************************************************************************************************************

复制代码
20、迭代器模式
【1】组合者模式解决过学校、学院、专业的问题。用一致的方法遍历集合元素。
【2】越来越难,强人所难呀,卧槽...

迭代器模式.zip

****************************************************************************************************************************************************************************

复制代码
21、观察者模式
【1】设计开放型的API
package com.day.service.imp;

import lombok.Data;

// 核心类   最新的天气信息、含有NowCondition、数据有更新就主动调用
@Data
public class WeatherData {
    private float hot;
    private float press;
    private float water;
    private NowCondition nowCondition;

    public WeatherData(NowCondition nowCondition) {
        this.nowCondition = nowCondition;
    }

    public void dataChange() {
        nowCondition.update(hot, press, water);
    }

    public void setData(float hot, float press, float water) {
        this.hot = hot;
        this.press = press;
        this.water = water;
        // 推送给接入方
        dataChange();
    }
}
*************************************
package com.day.service.imp;

public class NowCondition {
    private float hot;
    private float press;
    private float water;

    // 更新天气
    public void update(float hot, float press, float water) {
        this.hot = hot;
        this.press = press;
        this.water = water;
        display();
    }

    public void display() {
        System.out.println("今天温度 " + hot);
        System.out.println("今天气压 " + press);
        System.out.println("今天湿度 " + water);
    }
}
*********************************
package com.day;

import com.day.service.imp.NowCondition;
import com.day.service.imp.WeatherData;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        NowCondition nowCondition = new NowCondition();
        WeatherData weatherData = new WeatherData(nowCondition);
        // 更新天气情况
        weatherData.setData(10.1f, 20.1f, 30.1f);
        // 天气变化
        System.out.println("天气情况发生变化..........................................................");
        weatherData.setData(20.1f, 30.1f, 40.1f);
    }
}
【2】观察者模式的改进
package com.day.service;

// 接口 WeatherData来实现
public interface Subject {
    public void regObserver(Observe observe);

    public void removeObserver(Observe observe);

    public void notifyObserver();
}
*********************************
package com.day.service;

// 观察者接口
public interface Observe {
    public void update(float hot, float press, float water);
}
*********************************
package com.day.service.imp;

import com.day.service.Observe;
import com.day.service.Subject;

import java.util.ArrayList;
import java.util.List;

public class WeatherData implements Subject {
    private float hot;
    private float press;
    private float water;
    private ArrayList<Observe> observeArrayList;

    public WeatherData() {
        observeArrayList = new ArrayList<>();
    }

    public void dataChange() {
        //nowCondition.update(hot, press, water);
        notifyObserver();
    }

    public void setData(float hot, float press, float water) {
        this.hot = hot;
        this.press = press;
        this.water = water;
        // 推送给接入方
        dataChange();
    }

    @Override
    public void regObserver(Observe observe) {
        observeArrayList.add(observe);
    }

    @Override
    public void removeObserver(Observe observe) {
        if (observeArrayList.contains(observe)) {
            observeArrayList.remove(observe);
        }
    }

    @Override
    public void notifyObserver() {
        for (Observe temp : observeArrayList) {
            temp.update(hot, press, water);
        }
    }
}
*********************************
package com.day.service.imp;

import com.day.service.Observe;

public class NowCondition implements Observe {
    private String coName;
    private float hot;
    private float press;
    private float water;

    public NowCondition(String coName) {
        this.coName = coName;
    }

    // 更新天气
    public void update(float hot, float press, float water) {
        this.hot = hot;
        this.press = press;
        this.water = water;
        display();
    }

    public void display() {
        System.out.println(coName + " 今天温度 " + hot);
        System.out.println(coName + " 今天气压 " + press);
        System.out.println(coName + " 今天湿度 " + water);
    }
}
*********************************
package com.day;

import com.day.service.imp.NowCondition;
import com.day.service.imp.WeatherData;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        NowCondition nowCondition = new NowCondition("新浪");
        NowCondition nowCondition_1 = new NowCondition("百度");
        WeatherData weatherData = new WeatherData();
        weatherData.regObserver(nowCondition); //注册
        weatherData.regObserver(nowCondition_1); //注册
        // 测试
        weatherData.setData(1f, 2f, 3f);
        //移出
        weatherData.removeObserver(nowCondition_1);
        weatherData.setData(1f, 2f, 3f);
    }
}

****************************************************************************************************************************************************************************

复制代码
22、备忘录模式
【1】在不破坏封装性的前提下,捕获一个对象的内部状态,后面可以恢复到保存前的状态。
package com.day.service.imp;

import java.util.ArrayList;
import java.util.List;

public class Care {
    private List<Memento> mementoList = new ArrayList<>();

    public void add(Memento memento) {
        mementoList.add(memento);
    }

    public Memento get(int index) {
        return mementoList.get(index);
    }
}
**********************************
package com.day.service.imp;

import lombok.Data;

@Data
public class Origin {
    private String state;

    // 可以保存状态对象的方法
    public Memento saveState() {
        return new Memento(state);
    }

    public void getState(Memento memento) {
        state = memento.getState();
    }
}
**********************************
package com.day.service.imp;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Memento {
    private String state;
}
**********************************
package com.day;

import com.day.service.imp.Care;
import com.day.service.imp.Origin;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        Origin origin = new Origin();
        Care care = new Care();
        origin.setState("状态1 :攻击力 100");
        care.add(origin.saveState()); // 保存当前状态
        origin.setState("状态2:攻击力 84");
        care.add(origin.saveState()); // 保存当前状态
        origin.setState("状态3:攻击力 92");
        care.add(origin.saveState()); // 保存当前状态
        // 当前状态
        System.out.println("当前状态 " + origin.getState());
        // 恢复到状态1
        origin.getState(care.get(0)); // 这里是关键
        System.out.println("回复到状态1 " + origin.getState());
    }
}

****************************************************************************************************************************************************************************

复制代码
23、状态模式
【1】抽奖活动。这个可能会很实用。

状态模式.zip

****************************************************************************************************************************************************************************

复制代码
24、策略模式
【1】管理不同种类鸭子的信息。让算法的变化独立于实用算法的客户。也是不同维度聚合、组合的思想。

****************************************************************************************************************************************************************************

复制代码
25、职责链模式
【1】解决交税类似问题。
【2】传统的switch是很难面对变动问题的。就是A能处理就处理,不能处理交给B,B能处理就处理,不能处理交给C...一个处理链路
package com.day.service;

import com.day.service.imp.PurchaseRequest;
import lombok.Data;

@Data
public abstract class Approver {
    public Approver approver; // 下一个处理者
    String name;// 姓名

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

    // 处理审批请求的方法
    public abstract void processRequest(PurchaseRequest purchaseRequest);
}
**********************************
package com.day.service.imp;

import lombok.Data;

@Data
public class PurchaseRequest {
    private int type;
    private float price = 0.0f;
    private int id = 0;

    //构造器
    public PurchaseRequest(int type, float price, int id) {
        super();
        this.type = type;
        this.price = price;
        this.id = id;
    }

}
**********************************
package com.day.service.imp;

import com.day.service.Approver;

public class DepartmentApprover extends Approver {

    public DepartmentApprover(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() <= 5000) {
            System.out.println("编号" + purchaseRequest.getId() + "被" + this.getName() + "处理");
        } else {
            getApprover().processRequest(purchaseRequest);
        }
    }
}
**********************************
package com.day.service.imp;

import com.day.service.Approver;

public class CollegeApprover extends Approver {
    public CollegeApprover(String name) {
        super(name);
    }

    @Override
    public void processRequest(PurchaseRequest purchaseRequest) {
        if (purchaseRequest.getPrice() > 5000 && purchaseRequest.getPrice() <= 10000) {
            System.out.println("编号" + purchaseRequest.getId() + "被" + this.getName() + "处理");
        } else {
            getApprover().processRequest(purchaseRequest);
        }
    }
}
**********************************
package com.day;

import com.day.service.imp.CollegeApprover;
import com.day.service.imp.DepartmentApprover;
import com.day.service.imp.PurchaseRequest;

// 主函数入口
public class DayApplication {
    public static void main(String[] args) throws Exception {
        PurchaseRequest purchaseRequest = new PurchaseRequest(1, 8000, 1001);
        DepartmentApprover departmentApprover = new DepartmentApprover("专业长");
        departmentApprover.setApprover(new CollegeApprover("院长")); // 这个设置很关键
        departmentApprover.processRequest(purchaseRequest);
    }
}
相关推荐
CocoaAndYy29 分钟前
设计模式-单例模式
单例模式·设计模式
bobostudio19952 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
ok!ko6 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
拉里小猪的迷弟7 小时前
设计模式-创建型-常用:单例模式、工厂模式、建造者模式
单例模式·设计模式·建造者模式·工厂模式
严文文-Chris9 小时前
【设计模式-中介者模式】
设计模式·中介者模式
刷帅耍帅9 小时前
设计模式-中介者模式
设计模式·中介者模式
刷帅耍帅10 小时前
设计模式-组合模式
设计模式·组合模式
刷帅耍帅11 小时前
设计模式-命令模式
设计模式·命令模式
码龄3年 审核中11 小时前
设计模式、系统设计 record part03
设计模式
刷帅耍帅11 小时前
设计模式-外观模式
设计模式·外观模式