****************************************************************************************************************************************************************************
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】生产工厂的工厂。根据不同的业务来写。对于稳定的业务,还是很强大的。
****************************************************************************************************************************************************************************
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】这个在实际的商城中也可以用到价格叠加,卧槽。
****************************************************************************************************************************************************************************
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();
}
}
****************************************************************************************************************************************************************************
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】这里还是需要深度理解下的。
****************************************************************************************************************************************************************************
20、迭代器模式
【1】组合者模式解决过学校、学院、专业的问题。用一致的方法遍历集合元素。
【2】越来越难,强人所难呀,卧槽...
****************************************************************************************************************************************************************************
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】抽奖活动。这个可能会很实用。
****************************************************************************************************************************************************************************
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);
}
}