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);
    }
}
相关推荐
杨充10 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充10 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充10 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充10 小时前
2.面向对象的特性
设计模式
杨充10 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充10 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充11 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯14 小时前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式