【Java基础学习】设计模式

这篇博客详细介绍了Java设计模式,包括创建型模式中的单例模式、工厂模式(简单工厂、工厂方法、抽象工厂)、建造者模式和原型模式。此外,还讨论了结构型模式如适配器模式、代理模式,以及行为型模式中的责任链模式、迭代器模式等。文章通过具体的例子和类图解释了每种模式的核心作用和实现方式。
摘要由CSDN通过智能技术生成

- 设计模式

- 创建型模式

- 单例模式

**作用:**保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
常见应用场景:
在这里插入图片描述优点:

  • 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式解决
  • 单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例,负责所有数据表的映射处理。
    常见的五种单例模式实现:
  • 主要:
    - 饿汉式(线程安全,调用效率高。但是不能延时加载)
public class SingletonDemo01 {
	
	//类初始化时(天然的线程安全)立即加载(没有延时加载的优势--用到的时候再加载)这个对象
	private static SingletonDemo01 instance=new SingletonDemo01();
	
	private SingletonDemo01() {
		
	}
	
	//该处不需要加同步方法,方法没有同步,调用效率高
	public static /*synchronzied*/SingletonDemo01 getInstance() {
		return instance;
	}
}
	- 懒汉式(线程安全,调用效率不高。但是能延时加载)
public class SingletonDemo02 {
	
	//类初始化时,不初始化这个对象(延时加载,真正用到时再创建)
	public static SingletonDemo02 instance;
	private SingletonDemo02() {
		
	}
	
	//方法有同步,调用效率低
	public static synchronized SingletonDemo02 getInstance() {
		if(instance==null) {
			instance=new SingletonDemo02();
		}
		return instance;
	}
}
  • 其他:
    - 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)
public class SingletonDemo3 {

	private static SingletonDemo3 instance = null;

	/**
	 * 只有第一次同步创建,之后就没必要了。由于编译器优化原因和JVM底层内部模型原因。偶尔会出问题,不建议使用
	 * @return
	 */
	public static SingletonDemo3 getInstance() {
		if (instance == null) {
			SingletonDemo3 sc;
			synchronized (SingletonDemo3.class) {
				sc = instance;
				if (sc == null) {
					synchronized (SingletonDemo3.class) {
						if (sc == null) {
							sc = new SingletonDemo3();
						}
					}
					instance = sc;
				}
			}
		}
		return instance;
	}

	private SingletonDemo3() {

	}

}
	- 静态内部类式(线程安全,调用效率高。但是能延时加载) 
public class SingletonDemo04 {
	
	//外部类没有像饿汉式那样的static属性,不会立即加载对象
	//只有真正调用getInstance()才会加载静态内部类。加载类时是线程安全的。instance是static final类型保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证线程安全
	//兼备:线程安全、效率高以及延迟加载的优势
	private static class SingletonClassInstance{
		private static final SingletonDemo04 instance=new SingletonDemo04();
	}
	
	private SingletonDemo04() {
		
	}
	
	public static SingletonDemo04 getInstance() {
		return SingletonClassInstance.instance;
	}
}
	- 枚举单例(线程安全,调用效率高。但是不能延时加载)
public enum SingletonDemo05 {
	
	//这个枚举元素,本身就是单例对象!
	//避免了反射(私有构造器也可以访问)以及反序列化的漏洞
	//没有延时加载
	INSTANCE;
	
	//添加自己需要的操作
	public void singletonOperation() {
		
	}
	
}

选择方式:

  • 需要延迟加载:静态内部类 好于 懒汉式;不需要延迟加载:枚举式 好于 饿汉式
    单例模式问题
  • 反射可以破解上述(除枚举式)实现方式(可以手动在构造器中抛出异常控制)
  • 反序列化可以破解上述(除枚举式)实现方式(可以通过定义readResolve()防止获得不同对象,反序列化时如果对象所在的类定义了readResolve()–实际是一种回调,定义返回那个对象)
    SingletonDemo06
public class SingletonDemo06 implements Serializable {
	
	//类初始化时,不初始化这个对象(延时加载,真正用到时再创建)
	public static SingletonDemo06 instance;
	private SingletonDemo06() {
		if(instance!=null) {
			throw new RuntimeException();
		}
	}
	
	//方法有同步,调用效率低
	public static synchronized SingletonDemo06 getInstance() {
		if(instance==null) {
			instance=new SingletonDemo06();
		}
		return instance;
	}
	//反序列化时,如果定义了readResolve方法,则直接返回此方法指定的对象,而不需要再创建新对象
	private Object readResolve() {
		return instance;
	}
}
public class Client2 {
	public static void main(String[] args) throws Exception {
		SingletonDemo06 s1=SingletonDemo06.getInstance();
		SingletonDemo06 s2=SingletonDemo06.getInstance();
		System.out.println(s1);
		System.out.println(s2);
		
		//通过反射直接调用私有构造器
		/*Class<SingletonDemo06> clazz=(Class<SingletonDemo06>) Class.forName("com.sxt.singleton.SingletonDemo06");
		Constructor<SingletonDemo06> c=clazz.getDeclaredConstructor(null);
		c.setAccessible(true);//跳过安全检查
		SingletonDemo06 s3=c.newInstance();
		SingletonDemo06 s4=c.newInstance();
		
		System.out.println(s3);
		System.out.println(s4);*/
		//SingletonDemo06为懒汉式实现
		/**不修改SingletonDemo06构造方法是的运行结果
		 *  com.sxt.singleton.SingletonDemo06@7852e922
			com.sxt.singleton.SingletonDemo06@7852e922
			com.sxt.singleton.SingletonDemo06@4e25154f
			com.sxt.singleton.SingletonDemo06@70dea4e
		 */
		/**修改SingletonDemo06构造方法if(instance!=null) {
			throw new RuntimeException();
			}之后运行结果
		 * com.sxt.singleton.SingletonDemo06@7852e922
			com.sxt.singleton.SingletonDemo06@7852e922
			Exception in thread "main" java.lang.reflect.InvocationTargetException
				at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
				at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
				at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
				at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
				at com.sxt.singleton.Client2.main(Client2.java:20)
			Caused by: java.lang.RuntimeException
				at com.sxt.singleton.SingletonDemo06.<init>(SingletonDemo06.java:13)
	... 5 more

		 */
		
		//通过反序列化的方式构造多个对象
		FileOutputStream fos=new FileOutputStream("F:/src/java/a.txt");
		ObjectOutputStream oos=new ObjectOutputStream(fos);
		oos.writeObject(s1);
		oos.close();
		fos.close();
		
		ObjectInputStream ois=new ObjectInputStream(new FileInputStream("F:/src/java/a.txt"));
		SingletonDemo06 s5=(SingletonDemo06)ois.readObject();
		System.out.println(s5);
		
		/**
		 * 运行结果
		 * com.sxt.singleton.SingletonDemo06@35f983a6
			com.sxt.singleton.SingletonDemo06@35f983a6
			com.sxt.singleton.SingletonDemo06@1e88b3c
		 */
		
		/**
		 * 加上readResolve方法之后的结果
		 * com.sxt.singleton.SingletonDemo06@7852e922
			com.sxt.singleton.SingletonDemo06@7852e922
			com.sxt.singleton.SingletonDemo06@7852e922

		 */
	}
}

各种实现的效率测试
在这里插入图片描述

public class Client3 {
	public static void main(String[] args) throws Exception {
		long start=System.currentTimeMillis();
		
		int threadNum=10;
		//CountDownLatch 同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待
		CountDownLatch countDownLatch=new CountDownLatch(threadNum);
		
		for (int i = 0; i < threadNum; i++) {
			new Thread(() -> {
				for (int j = 0; j < 100000; j++) {
//					Object o = SingletonDemo04.getInstance();
					Object o = SingletonDemo05.INSTANCE;
				}
				countDownLatch.countDown();//当前线程调用此方法则计数减一,建议在finally中执行
			}).start();
		}
		
		countDownLatch.await();//main线程阻塞直到计数器变成0,才会继续往下执行
		long end=System.currentTimeMillis();
		System.out.println("总耗时:"+(end-start));
	}
}

- 工厂模式

工厂模式

  • 实现了创建者和调用者的分离
  • 详细分类:
    - 简单工厂模式:用来生产同一等级结构中的任意产品(对于新增加的产品,需要修改已有代码)
    - 工厂方法模式:用来生产同一等级结构中的固定产品(支持新增任意产品)
    - 抽象工厂模式:用来生产不同产品族的全部产品(对于新增产品,无能为力;支持新增产品族)
    面向对象设计的基本原则
  • OCP(开闭原则,Open-Closed Principle):一个软件的实体应当对扩展开放,对修改关闭
  • DIP(依赖倒转原则,Dependence Inversion Principle):要针对接口编程,不要针对实现编程
  • LoD(迪米特法则,Law of Demeter):只与你直接的朋友通讯,而避免和陌生人通信
    核心本质
  • 实例化对象,用工厂方法代替new操作
  • 将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦
简单工厂模式实现
  • 简单工厂模式也叫静态工厂模式,就是工厂类一般是使用静态方法,通过接收的参数的不同来返回不同的实例对象
  • 对于增加新产品无能为力,不修改代码的话,无法扩展。
    Car 接口
public interface Car {
	void run();
}
public class Audi implements Car {
	@Override
	public void run() {
		System.out.println("奥迪在跑!");
		
	}
}
public class Byd implements Car {
	@Override
	public void run() {
		System.out.println("比亚迪在跑!");
		
	}
}
public class CarFactory {
	//此代码并没满足开闭原则,因新增车型时需要修改代码,这也是简单工厂模式的问题
	//实现方式1:
	public static Car creatCar(String type) {
		if("奥迪".equals(type)) {
			return new Audi();
		}else if("比亚迪".equals(type)) {
			return new Byd();
		}else {
			return null;
		}
	}
	
	//实现方式2:
	public static Car createAudi() {
		return new Audi();
	}
	public static Car createByd() {
		return new Byd();
	}
}

不使用工厂模式:

public class Client01 {//调用者:需要知道Car Audi Byd等信息
	public static void main(String[] args) {
		Car c1=new Audi();
		Car c2=new Byd();
		
		c1.run();
		c2.run();
	}
}

使用工厂模式:

public class Client02 {//调用者:只需要知道Car CarFactory
	public static void main(String[] args) {
		Car c1=CarFactory.creatCar("奥迪");
		Car c2=CarFactory.creatCar("比亚迪");
		c1.run();
		c2.run();
	}
}
工厂方法模式
public interface CarFactory {
	Car createCar();
}

public class AudiFactory implements CarFactory{
	@Override
	public Car createCar() {
		return new Audi();
	}

}
public class BydFactory implements CarFactory{
	@Override
	public Car createCar() {
		return new Byd();
	}

}
public class Client {
	public static void main(String[] args) {
		Car c1=new AudiFactory().createCar();
		c1.run();
		
		Car c2=new BydFactory().createCar();
		c2.run();
	}
}

与简单工厂模式的比较
在这里插入图片描述

抽象工厂模式

Engine、Seat和Tyre形成产品族,类图中有两个产品族:LuxuryCarFactory创建的高端产品族,LowCarFactory创建的低端产品族

在这里插入图片描述

总结

在这里插入图片描述

- 建造者模式

建造者模式的本质
在这里插入图片描述
示例类图如下:
AirShipDirector用于组装各种组件,AirShipBuilder用于构建各种组件,前者引用后者并对其组装。在AirShipBuilder的实现类中,构建组件时可以与工厂模式结合

在这里插入图片描述

- 原型模式

  • 通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式
  • 原型模式可以和工厂模式一起使用,当工厂模式底层创建对象时可以使用原型模式

简单实现

//Cloneable 标记接口 类似 Serializable
public class Sheep implements Cloneable{
	private String sname;
	private Date birthday;
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj=super.clone();//直接调用Object对象的clone方法
		return obj;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public Sheep() {
		super();
	}

	public Sheep(String sname, Date birthday) {
		super();
		this.sname = sname;
		this.birthday = birthday;
	}	
}
public class Client {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date=new Date(13241234124L);
		Sheep s1=new Sheep("少利",date);
		
		System.out.println(s1);
		System.out.println(s1.getSname()+"---->"+s1.getBirthday());
		
		Sheep s2=(Sheep) s1.clone();
		
		System.out.println(s2);
		//克隆的对象与原对象保持一样的值
		System.out.println(s2.getSname()+"---->"+s2.getBirthday());
		//可以修改
		s2.setSname("多利");
		System.out.println(s2.getSname()+"---->"+s2.getBirthday());
		
		//浅克隆时,date发生改变 s1、s2都会发生改变,因其属性都指向date,没有进行克隆
		//深克隆时,s1、s2有各自的date值
	}
}

在clone中实现深克隆

protected Object clone() throws CloneNotSupportedException {
		Object obj=super.clone();//直接调用Object对象的clone方法
		
		//添加如下代码实现深复制(deep clone),取掉该代码为浅复制
		Sheep s=(Sheep)obj;
		s.birthday=(Date) this.birthday.clone();
		
		
		return obj;
	}

用序列化和反序列化实现深克隆

public class Client3 {
	public static void main(String[] args) throws Exception {
		Date date = new Date(234114341L);
		Sheep s1 = new Sheep("少利", date);
		

		System.out.println(s1);
		System.out.println(s1.getSname() + "--->" + s1.getBirthday());
        //Sheep2 s2 = (Sheep2) s1.clone();
		// 使用序列化和反序列化实现深复制
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(bos);

		oos.writeObject(s1);
		byte[] bytes = bos.toByteArray();

		ByteArrayInputStream bis=new ByteArrayInputStream(bytes);
		ObjectInputStream ois=new ObjectInputStream(bis);
		Sheep s2=(Sheep)ois.readObject();//克隆好的对象 
		
		date.setTime(2341241341L);
		System.out.println(s1.getSname() + "--->" + s1.getBirthday());

		s2.setSname("多利");
		System.out.println(s2.getSname() + "-->" + s2.getBirthday());

	}
}

- 创建型模式总结

创建型模式都是帮助我们创建对象

- 结构型模式

  • 核心作用:从程序结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题

- 适配器模式

在这里插入图片描述
简单实现
在这里插入图片描述

  • 适配器的实现有两种方式:1、直接继承被适配的类,然后直接通过super调用其中方法,弊端是java单继承 2、通过组合方式,适配器类引用被适配类对象
/**
 * 被适配的类
 * PS/2键盘(PS/2接口通过适配器连接usb接口的笔记本)
 *
 */
public class Adaptee {
	public void request() {
		System.out.println("可以完成客户请求的需要功能!!");
	}
}

public interface Target {
	void handleReq();
}
/**
 * 客户端类
 * 笔记本(PS/2接口通过适配器连接usb接口的笔记本)
 *
 */
public class Client {
	public void test1(Target t) {
		t.handleReq();
	}
	
	public static void main(String[] args) {
		Client c=new Client();
		
		Adaptee a=new Adaptee();
		
//		Target t=new Adapter();
		Target t=new Adapter2(a);
		
		c.test1(t);
	}
}
/**
 * 适配器(类适配器方式)
 * USB与PS/2的转接器
 *
 */
public class Adapter extends Adaptee implements Target {
	
	
	@Override
	public void handleReq() {
		super.request();
	}
}

/**
 * 适配器(对象适配器方式,使用了组合跟被适配对象整合)
 * USB与PS/2的转接器
 *  */
public class Adapter2 implements Target {
	private Adaptee adaptee;
	
	@Override
	public void handleReq() {
		adaptee.request();
	}
	
	public Adapter2(Adaptee adaptee) {
		this.adaptee=adaptee;
	}
}

- 代理模式

  • 核心作用:通过代理,控制对对象的访问。可以详细控制访问某个(某类)对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。(即:AOP的微观实现)
  • AOP(Aspect Oriented Programming面向切面编程)的核心实现机制
    在这里插入图片描述
    在这里插入图片描述
静态代理(static proxy )

简单实现

public interface Star {

	/**
	 * 面谈
	 */
	void confer();

	/**
	 * 签合同
	 */
	void signContract();

	/**
	 * 订票
	 */
	void bookTicket();

	/**
	 * 唱歌
	 */
	void sing();

	/**
	 * 收钱
	 */
	void collectMoney();
}
public class ProxyStar implements Star{
	
	private Star star;
	public ProxyStar(Star star) {
		this.star=star;
	}
	@Override
	public void bookTicket() {
		System.out.println("ProxyStar.bookTicket()");
		
	}@Override
	public void collectMoney() {
		System.out.println("ProxyStar.collectMoney()");
	}
	@Override
	public void confer() {
		System.out.println("ProxyStar.confer()");
	}
	@Override
	public void signContract() {
		System.out.println("ProxyStar.signContract()");
	}@Override
	public void sing() {
		star.sing();
	}
}
public class RealStar implements Star{
	@Override
	public void bookTicket() {
		System.out.println("RealStar.bookTicket()");
	}
	@Override
	public void collectMoney() {
		System.out.println("RealStar.collectMoney()");
		
	}@Override
	public void confer() {
		System.out.println("RealStar.confer()");
		
	}@Override
	public void signContract() {
		System.out.println("RealStar.signContract()");
	}
	@Override
	public void sing() {
		System.out.println("RealStar.sing()");
	}
}
public class Client {
	public static void main(String[] args) {
		Star real=new RealStar();
		Star proxy=new ProxyStar(real);
		proxy.confer();
		proxy.signContract();
		proxy.bookTicket();
		proxy.sing();
		proxy.collectMoney();
	}
}
动态代理(dynamic proxy )

JDK自带的动态代理

public class StarHandler implements InvocationHandler{
	Star realStar;
	
	public StarHandler(Star realStar) {
		super();
		this.realStar = realStar;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object object=null;
		
		System.out.println("唱歌前处理");
		if(method.getName().equals("sing")) {
			object=method.invoke(realStar, args);
		}
		System.out.println("唱歌后处理");
		return object;
	}
}
public class Client {
	public static void main(String[] args) {
		Star realStar =new RealStar();
		StarHandler hanlder=new StarHandler(realStar);
		Star proxy=(Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] {Star.class}, hanlder);
		proxy.sing();
	}
}

- 桥接模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/**
 * 电脑品牌维度
 *
 */
public interface Brand {
	void sale();
}


class Lenovo implements Brand{
	@Override
	public void sale() {
		System.out.println("销售联想电脑");
	}
}

class Hasee implements Brand{
	@Override
	public void sale() {
		System.out.println("销售神舟电脑");
	}
}
/**
 * 电脑类型维度
 *
 */
public class Computer {//不能使用接口因为有一个属性 需要子类访问
	protected Brand brand;

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

class Desktop extends Computer{

	public Desktop(Brand brand) {
		super(brand);
	}
	
	@Override
	public void sale() {
		super.sale();
		System.out.println("销售台式机");
	}
}


class Laptop extends Computer{

	public Laptop(Brand brand) {
		super(brand);
	}
	
	@Override
	public void sale() {
		super.sale();
		System.out.println("销售笔记本");
	}
}
public class Client {
	public static void main(String[] args) {
		//销售联想的笔记本电脑
		Computer c=new Laptop(new Lenovo());
		c.sale();
	}
}

- 组合模式

  • 组合模式中的“组合”跟之前Java基础中-组合不一样(A类包含B类对象的引用)
  • 组合模式十分适合解决树形结构
  • 容器、叶子都实现或继承构建,故其有统一的方式处理
    在这里插入图片描述
    在这里插入图片描述
//抽象构建
public interface AbstractFile {
	void killVirus();//杀毒
}

//叶子
class ImageFile implements AbstractFile{
	private String name;
	public ImageFile(String name) {
		super();
		this.name = name;
	}
	@Override
	public void killVirus() {
		System.out.println("----图像文件:"+name+",进行查杀----");
	}
}
//叶子
class TextFile implements AbstractFile{
	private String name;
	
	
	public TextFile(String name) {
		super();
		this.name = name;
	}


	@Override
	public void killVirus() {
		System.out.println("----文本文件:"+name+",进行查杀----");
	}
}
//叶子
class VideoFile implements AbstractFile{
	private String name;
	public VideoFile(String name) {
		super();
		this.name = name;
	}
	@Override
	public void killVirus() {
		System.out.println("----视频文件:"+name+",进行查杀----");
	}
}
//容器
class Folder implements AbstractFile{
	private String name;
	//存容器构建下面的子节点
	private List<AbstractFile> list=new ArrayList<AbstractFile>();
	public Folder(String name) {
		super();
		this.name = name;
	}
	
	public void add(AbstractFile file) {
		list.add(file);
	}

	public void remove(AbstractFile file) {
		list.remove(file);
	}
	
	public AbstractFile getChild(int index) {
		return list.get(index);
	}
	
	@Override
	public void killVirus() {
		System.out.println("----文件夹:"+name+",进行查杀");
		for(AbstractFile file:list) {
			file.killVirus();
		}
	}
}
public class Client {
	public static void main(String[] args) {
		AbstractFile f2,f3,f4,f5,f6;
		Folder f1=new Folder("我的收藏");
		
		f2=new ImageFile("头像.jpg");
		f3=new TextFile("hello.txt");
		f1.add(f2);
		f1.add(f3);
		
		Folder f11=new Folder("电影");
		f4=new VideoFile("我和我的家乡.mp4");
		f5=new VideoFile("我和我的祖国.mp4");
		f11.add(f4);
		f11.add(f5);
		f1.add(f11);
		
		f2.killVirus();
		f1.killVirus();
	}
}

- 装饰模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public interface ICar {
	void move();
}


//ConcreteComponent 具体构建角色(真实对象)
class Car implements ICar{
	@Override
	public void move() {
		System.out.println("陆地上跑!!");
	}
}

//Decorator装饰角色
class SuperCar implements ICar{
	protected ICar car;
	
	
	public SuperCar(ICar car) {
		super();
		this.car = car;
	}

	@Override
	public void move() {
		car.move();
	}
}
//ConcreteDecorator具体装饰对象
class FlyCar extends SuperCar{
	public FlyCar(ICar car) {
		super(car);
	}

	public void fly() {
		System.out.println("天上飞");
	}
	
	@Override
	public void move() {
		super.move();
		fly();
	}
}

//ConcreteDecorator具体装饰对象
class WaterCar extends SuperCar{
	public WaterCar(ICar car) {
		super(car);
	}

	public void swim() {
		System.out.println("水上游");
	}
	
	@Override
	public void move() {
		super.move();
		swim();
	}
}

//ConcreteDecorator具体装饰对象
class AIrCar extends SuperCar{
	public AIrCar(ICar car) {
		super(car);
	}

	public void autoMove() {
		System.out.println("自动跑游");
	}
	
	@Override
	public void move() {
		super.move();
		autoMove();
	}
}
public class Client {
	public static void main(String[] args) {
		ICar car=new Car();
		car.move();
		System.out.println("增加----->飞行");
		ICar flycar=new FlyCar(car);
		flycar.move();
		System.out.println("增加----->水上游");
		ICar watercar=new WaterCar(flycar);
		watercar.move();
	}
}

IO类中的装饰模式
在这里插入图片描述
总结
在这里插入图片描述
装饰模式与桥接模式的区别
在这里插入图片描述

  • 桥接模式解决多维度继承的问题,装饰模式解决多功能组合的问题

- 外观模式(门面模式)

  • 核心:为子系统提供统一的入口,封装子系统的复杂性,便于客户端调用
  • 遵循迪米特法则-最少知识原则,一个软件实体应当尽可能少的与其他实体发生相互作用

- 享元模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
享元模式设计思路:

  • 创建真实享元对象的工厂类:包含享元池用于存储创建的尚未存在的享元类对象,一般设计成键值对
  • 区分内部状态和外部状态,分别设计成不同的类
    针对上述五子棋的简单实现
/**
 * 享元类 抽象享元类FlyWeight
 *
 */
public interface ChessFlyWeight {
	void setColor(String c);
	String getColor();
	void display(Coordinate c);
}


/**
 * 具体享元类
 * @author yinqq
 *
 */
class ConcreteChess implements ChessFlyWeight{
	private String color;
	
	
	public ConcreteChess(String color) {
		super();
		this.color = color;
	}
	
	@Override
	public void display(Coordinate c) {
		System.out.println("棋子颜色:"+color);
		System.out.println("棋子位置:"+c.getX()+"-----"+c.getY());
		
	}
	@Override
	public String getColor() {
		return null;
	}
	@Override
	public void setColor(String c) {
		this.color=c;
	}
}
/**
 * 享元工厂类
 *
 */
public class ChessFlyWeightFactory {
	//享元池
	private static Map<String,ChessFlyWeight> map=new HashMap<String, ChessFlyWeight>();
	
	public static ChessFlyWeight getChess(String color) {
		if(map.get(color)!=null) {
			return map.get(color);
		}else {
			ChessFlyWeight cfw=new ConcreteChess(color);
			map.put(color, cfw);
			return cfw;
		}
	}
}
/**
 * 外部状态 非共享享元类UnSharedConcreteFlyWeight
 *
 */
public class Coordinate {
	private int x,y;

	public Coordinate(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}
	
}
public class Client {
	public static void main(String[] args) {
		//内部状态共享
		ChessFlyWeight chess1=ChessFlyWeightFactory.getChess("黑色");
		ChessFlyWeight chess2=ChessFlyWeightFactory.getChess("黑色");
		
		System.out.println(chess1);
		System.out.println(chess2);
		
		//外部状态变化
		System.out.println("增加外部状态的处理");
		chess1.display(new Coordinate(10,10));
		chess2.display(new Coordinate(20,20));
		
	}
}

- 行为模式

- 责任链模式

在这里插入图片描述
创建责任链模式的关键

  • 抽象类:责任链对象,包含后续责任链对象引用
  • 责任链的先后关系
    举例:公司请假审批
/**
 * 抽象类
 *
 */
public abstract class Leader {
	protected String name;
	protected Leader nextLeader;//责任链上的后继对象
	public Leader(String name) {
		super();
		this.name = name;
	}
	//设置责任链上的后继对象
	public void setNextLeader(Leader nextLeader) {
		this.nextLeader = nextLeader;
	}
	
	/**
	 * 处理请求的核心的业务方法
	 * @param request
	 */
	public abstract void handleRequest(LeaveRequest request);
}
/**
 * 主管
 *
 */
public class Director extends Leader{
	
	
	public Director(String name) {
		super(name);
	}

	@Override
	public void handleRequest(LeaveRequest request) {
		if(request.getLeaveDays()<3) {
			System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
			System.out.println("主任:"+this.name+",审批通过!");
		}else {
			if(this.nextLeader!=null) {
				nextLeader.handleRequest(request);
			}
		}
	}
	
}
/**
 * 经理
 *
 */
public class Manager extends Leader{
	
	
	public Manager(String name) {
		super(name);
	}

	@Override
	public void handleRequest(LeaveRequest request) {
		if(request.getLeaveDays()<10) {
			System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
			System.out.println("经理:"+this.name+",审批通过!");
		}else {
			if(this.nextLeader!=null) {
				nextLeader.handleRequest(request);
			}
		}
	}
	
}
/**
 * 封装请假的基本信息
 *
 */
public class LeaveRequest {
	private String empName;
	private int leaveDays;
	private String reason;
	
	
	
	
	public LeaveRequest(String empName, int leaveDays, String reason) {
		super();
		this.empName = empName;
		this.leaveDays = leaveDays;
		this.reason = reason;
	}
	public String getEmpName() {
		return empName;
	}
	public void setEmpName(String empName) {
		this.empName = empName;
	}
	public int getLeaveDays() {
		return leaveDays;
	}
	public void setLeaveDays(int leaveDays) {
		this.leaveDays = leaveDays;
	}
	public String getReason() {
		return reason;
	}
	public void setReason(String reason) {
		this.reason = reason;
	}
	
	
}
/**
 * 总经理
 *
 */
public class GeneralManager extends Leader{
	
	
	public GeneralManager(String name) {
		super(name);
	}

	@Override
	public void handleRequest(LeaveRequest request) {
		if(request.getLeaveDays()<30) {
			System.out.println("员工:"+request.getEmpName()+"请假,天数:"+request.getLeaveDays()+",理由:"+request.getReason());
			System.out.println("总经理:"+this.name+",审批通过!");
		}else {
			System.out.println("莫非"+request.getEmpName()+"想辞职,居然请假:"+request.getLeaveDays());
		}
	}
	
}
public class Client {
	public static void main(String[] args) {
		Leader director=new Director("张三");
		Leader manager=new Manager("李四");
		Leader generalManager=new GeneralManager("王五");
		
		//组织责任链对象关系
		director.setNextLeader(manager);
		manager.setNextLeader(generalManager);
		
		//开始请假操作
		LeaveRequest req1=new LeaveRequest("Tom", 1, "回英国老家探亲");
		director.handleRequest(req1);
		
	}
}

- 迭代器模式

在这里插入图片描述
自定义迭代器

  • 迭代器接口
  • 具体迭代器,一般为内部类,为外部类服务并可直接操作外部类属性
/**
 * 迭代器接口
 *
 */
public interface MyIterator {
	void first();//将游标指向第一个
	void next();//将游标指向下一个
	boolean hasNext();//判断是否存在下一个元素
	
	boolean isFirst();
	boolean isLast();
	
	Object getCurrentObj();//获取当前游标指向的对象
}
/**
 * 自定义的聚合类
 *
 */
public class ConcreteMyAggregate {
	private List<Object> list=new ArrayList<>();

	public ConcreteMyAggregate() {
	}
	
	//获得迭代器
	public MyIterator createIterator() {
		return new ConcreteIterator();
	}
	public void addObject(Object obj) {
		this.list.add(obj);
	}
	
	public void removeObject(Object obj) {
		this.list.remove(obj);
	}


	public List<Object> getList() {
		return list;
	}


	public void setList(List<Object> list) {
		this.list = list;
	}
	
	
	//内部类:可以直接操作外部类对象的属性和方法,只为外部类提供服务
	private class ConcreteIterator implements MyIterator{
		
		private int cursor=0;//定义游标用于记录遍历时的位置
		@Override
		public void first() {
			cursor=0;
		}

		@Override
		public void next() {
			if(cursor<list.size()) {
				cursor++;
			}
		}

		@Override
		public boolean hasNext() {
			if(cursor<list.size()) { 
				return true;
			}
			return false;
		}

		@Override
		public boolean isFirst() {
			return cursor==0?true:false;
		}

		@Override
		public boolean isLast() {
			return cursor==(list.size()-1)?true:false;
		}

		@Override
		public Object getCurrentObj() {
			return list.get(cursor);
		}
		
	}
}

public class Client {
	public static void main(String[] args) {
		ConcreteMyAggregate cma=new ConcreteMyAggregate();
		cma.addObject("aa");
		cma.addObject("cc");
		cma.addObject("bb");
		
		MyIterator iter=cma.createIterator();
		while(iter.hasNext()) {
			System.out.println(iter.getCurrentObj());
			iter.next();
		}
	}
}

- 迭代器模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
中介者模式的使用

  • 同事接口:内部方法+外部方法(用来调用中介者对象)
  • 具体同事类:包含中介者对象的引用+同事接口的具体实现
  • 中介者接口:包含方法:注册各个同事对象+调用各个同事对象
  • 具体中介者:包含HashMap存储同事对象+中介者接口的具体实现
    例如
public interface Mediator {
	void register(String name,Department d);
	void command(String name);
}
public class President implements Mediator {
	
	private Map<String,Department> map=new HashMap<String,Department>();
	@Override
	public void command(String dname) {
		map.get(dname).selfAction();
		
	}
	
	@Override
	public void register(String dname, Department d) {
		map.put(dname, d);
	}
	
}
//同事类接口
public interface Department {
	void selfAction();//做本部门的事情
	void outAction();//向总经理发出申请
}
public class Development implements Department {
	
	private Mediator m;//持有中介者(总经理)的引用
	
	
	public Development(Mediator m) {
		super();
		this.m = m;
		m.register("development", this);
	}
	
	@Override
	public void outAction() {
		System.out.println("汇报工作!没钱了,需要资金支持!");
	}
	@Override
	public void selfAction() {
		System.out.println("专心科研,开发项目!");
	}

}
public class Finacial implements Department {
	
	private Mediator m;//持有中介者(总经理)的引用
	
	
	public Finacial(Mediator m) {
		super();
		this.m = m;
		m.register("finacial", this);
	}
	
	@Override
	public void outAction() {
		System.out.println("汇报工作!钱太多了,怎么花?");
	}
	@Override
	public void selfAction() {
		System.out.println("数钱!");
	}

}
public class Market implements Department {
	
	private Mediator m;//持有中介者(总经理)的引用
	
	
	public Market(Mediator m) {
		super();
		this.m = m;
		m.register("market", this);
	}
	
	@Override
	public void outAction() {
		System.out.println("汇报工作!项目承接的进度,需要资金支持");
		m.command("finacial");
	}
	@Override
	public void selfAction() {
		System.out.println("跑去接项目!");
	}

}
public class Client {
	public static void main(String[] args) {
		Mediator m=new President();
		
		Market market=new Market(m);
		Development devp=new Development(m);
		Finacial f=new Finacial(m);
		
		market.selfAction();
		market.outAction();
	}
}	

--运行结果:
跑去接项目!
汇报工作!项目承接的进度,需要资金支持
数钱!

- 命令模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
命令模式的实现

  • 命令接口
  • 具体命令类:包含执行者的引用,通过其找到最终的命令执行者
  • 调用者类:包含命令类的引用,通过其执行命令
  • 命令执行者类
public interface Command {
	/**
	 * 这个方法是一个返回结果为空的方法
	 * 实际项目中,可以根据需求设计多个不同的方法
	 */
	void execute();
}

class ConcreteCommand implements Command{
	
	private Receiver receiver;
	
	public ConcreteCommand(Receiver receiver) {
		super();
		this.receiver = receiver;
	}

	@Override
	public void execute() {
		//命令真正执行前或后,执行相关的处理
		receiver.action();
	}
}
//调用者、发起者
public class Invoke {
	private Command command;//可以多条命令 可以通过容器List<Command>容纳很多命令对象,进行批处理

	public Invoke(Command command) {
		super();
		this.command = command;
	}
	
	//业务方法,用于调用命令类的方法
	public void call() {
		command.execute();
	}
}
//真正的命令执行者
public class Receiver {
	public void action() {
		System.out.println("Receiver.action()");
	}
}
public class Client {
	public static void main(String[] args) {
		Command c=new ConcreteCommand(new Receiver());
		
		Invoke i=new Invoke(c);
		
		i.call();
	}
}
--运行结果:
Receiver.action()

- 解释器模式

在这里插入图片描述
在这里插入图片描述

- 访问者模式

在这里插入图片描述

- 策略模式strategy

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实现策略模式:

  • Context类与算法的实现打交道,引用其公共接口的引用
  • 客户端与Context交互
public interface Strategy {
	public double getPrice(double standardPrice);
}
public class NewCustomerFewStrategy implements Strategy {
	@Override
	public double getPrice(double standardPrice) {
		System.out.println("不打折,原价!");
		return standardPrice;
	}

}
public class OldCustomerFewStrategy implements Strategy {
	@Override
	public double getPrice(double standardPrice) {
		System.out.println("打八五折!");
		return standardPrice * 0.85;
	}

}

public class OldCustomerManyStrategy implements Strategy {
	@Override
	public double getPrice(double standardPrice) {
		System.out.println("打八折!");
		return standardPrice * 0.8;
	}

}
/**
 * 负责和具体的策略类交互
 * 这样话,具体的算法和直接的客户端调用分离,使得算法可以独立于客户端独立的变化
 * 
 * 如果使用spring的依赖注入功能,还可以通过配置文件,动态的注入不同的策略对象,动态的切换不同的算法
 *
 */
public class Context {
	private Strategy strategy;//当前采用的算法

	//可以通过构造器来注入
	public Context(Strategy strategy) {
		super();
		this.strategy = strategy;
	}

	//可以通过set方法来注入
	public void setStrategy(Strategy strategy) {
		this.strategy = strategy;
	}
	
	public void printPrice(double s) {
		System.out.println("您的报价:"+strategy.getPrice(s));
	}
	
	
}
public class Client {
	public static void main(String[] args) {
		Strategy s1=new OldCustomerManyStrategy();
		Context ctx=new Context(s1);
		
		ctx.printPrice(998);
	}
}

- 模板方法模式template method

在这里插入图片描述

在这里插入图片描述
实现模板方法模式

  • 固定的模板-流程+其中易变的部分
  • 模板抽象类
  • 子类实现具体方法
public abstract class BankTemplateMethod {
	public void takeNumber() {
		System.out.println("取号排队");
	}
	
	//办理具体业务 钩子方法
	public abstract void transact();
	
	public void evaluate() {
		System.out.println("反馈评分");
	}
	
	public final void process() {
		this.takeNumber();
		this.transact();
		this.evaluate();
	}
}
public class Client {
	public static void main(String[] args) {
		BankTemplateMethod btm=new DrawMoney();
		btm.process();
		System.out.println("---------------------------");
		//一般情况下采用匿名内部类
		BankTemplateMethod btm2=new BankTemplateMethod() {
			@Override
			public void transact() {
				System.out.println("我要存钱");
			}
		};
		btm2.process();
	}
}


class DrawMoney extends BankTemplateMethod{
	
	@Override
	public void transact() {
		System.out.println("我要取款");
	}
}

- 状态模式state

在这里插入图片描述
在这里插入图片描述
实现状态模式

  • 不同状态以及相互间的转换关系
  • Context上下文类引用状态接口的引用,其代表当前状态
public interface State {
	void handle();
}
/**
 * 已预定状态
 *
 */
public class BookedState implements State{
	@Override
	public void handle() {
		System.out.println("房间已预定!别人不能定!");
	}
}
/**
 * 已入住状态
 *
 */
public class CheckedInedState implements State{
	@Override
	public void handle() {
		System.out.println("房间已入住!请勿打扰!");
	}
}

public class RoomContext {
	//如果是银行系统,这个Context类就是账户,根据金额不同切换不同的状态
	private State state;
	
	public void setState(State s) {
		System.out.println("修改状态!");
		this.state=s;
		state.handle();
	}
}	
public class Client {
	public static void main(String[] args) {
		RoomContext ctx=new RoomContext();
		
		ctx.setState(new FreeState());
		
		ctx.setState(new BookedState());
		
	}
}

- 观察者模式observer

在这里插入图片描述
实现观察者模式

  • 目标对象
  • 观察者对象
  • 目标父类,包含公共方法:注册移除观察者对象、通知观察者对象
  • 观察者接口,包含公共方法:更新状态
public class Subject {
	private List<Observer> list=new ArrayList<Observer>();
	
	public void registerObserver(Observer  obs) {
		list.add(obs);
	}
	
	public void removeObserver(Observer  obs) {
		list.remove(obs);
	}
	
	//通知所有观察者更新状态
	public void notifyAllObserver() {
		for(Observer obs:list) {
			obs.update(this);
		}
	}
}
public class ConcreteSubject extends Subject{
	private int state;

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
		
		//主题对象(目标对象),请通知所有观察者
		this.notifyAllObserver();
	}
}
public interface Observer {
	void update(Subject subject);
}
public class ObserverA implements Observer{
	private int myState;//myState需要跟目标对象的state保持一致
	
	@Override
	public void update(Subject subject) {
		myState=((ConcreteSubject)subject).getState();
	}

	public int getMyState() {
		return myState;
	}

	public void setMyState(int myState) {
		this.myState = myState;
	}
	
	
}
public class Client {
	public static void main(String[] args) {
		//目标对象
		ConcreteSubject subject=new ConcreteSubject();
		
		//创建多个观察者
		ObserverA obs1=new ObserverA();
		ObserverA obs2=new ObserverA();
		ObserverA obs3=new ObserverA();
		
		//三个观察者添加到subject观察者对象容器中
		subject.registerObserver(obs1);
		subject.registerObserver(obs2);
		subject.registerObserver(obs3);
		
		//改变subject状态
		subject.setState(3000);
		
		//查看观察者的状态变化
		System.out.println(obs1.getMyState());
		System.out.println(obs2.getMyState());
		System.out.println(obs3.getMyState());
		
	}
}

JAVASE自带实现

  • java.util.Observable和java.util.Observer
public class ObserverA implements Observer{
	private int myState;
	
	@Override
	public void update(Observable o, Object arg) {
		myState=((ConcreteSubject)o).getState();
	}

	public int getMyState() {
		return myState;
	}

	public void setMyState(int myState) {
		this.myState = myState;
	}
	
	
}
//目标对象
public class ConcreteSubject extends Observable{
	private int state;

	public void setState(int state) {
		this.state = state;//目标对象的状态发生了变化
		setChanged();//表示目标对象已经做了更改
		notifyObservers(state);//通知所有观察者
	}

	public int getState() {
		return state;
	}
		
}
public class Client {
	public static void main(String[] args) {
		// 目标对象
		ConcreteSubject subject = new ConcreteSubject();

		// 创建多个观察者
		ObserverA obs1 = new ObserverA();
		ObserverA obs2 = new ObserverA();
		ObserverA obs3 = new ObserverA();

		// 三个观察者添加到subject观察者对象容器中
		subject.addObserver(obs1);
		subject.addObserver(obs2);
		subject.addObserver(obs3);
		

		// 改变subject状态
		subject.setState(3020);

		// 查看观察者的状态变化
		System.out.println(obs1.getMyState());
		System.out.println(obs2.getMyState());
		System.out.println(obs3.getMyState());
	}
}

在这里插入图片描述

- 备忘录模式memento

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

/**
 * 源发器类
 *
 */
public class Emp {
	private String ename;
	private int age;
	private double salary;
	
	//进行备忘操作,并返回备忘录对象
	public EmpMemento memento() {
		return new EmpMemento(this);
	}
	
	//进行数据恢复,恢复成指定备忘录对象的值
	public void recovery(EmpMemento mmt) {
		this.ename=mmt.getEname();
		this.age=mmt.getAge();
		this.salary=mmt.getSalary();
	}
	
	
	
	
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	
	
	public Emp(String ename, int age, double salary) {
		super();
		this.ename = ename;
		this.age = age;
		this.salary = salary;
	}
	
}
/**
 * 备忘录类
 *
 */
public class EmpMemento {
	private String ename;
	private int age;
	private double salary;
	
	public EmpMemento(Emp e) {
		this.ename=e.getEname();
		this.age=e.getAge();
		this.salary=e.getSalary();
	}
	
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	
}
/**
 * 负责人类
 * 负责管理备忘录对象
 *
 */
public class CareTaker {
	private EmpMemento memento;
	//通过容器可以存储多个备忘点,也可以按照键值对存储

	public EmpMemento getMemento() {
		return memento;
	}

	public void setMemento(EmpMemento memento) {
		this.memento = memento;
	}	
}
public class Client {
	public static void main(String[] args) {
		CareTaker taker=new CareTaker();
		
		Emp emp=new Emp("张三",18,900);
		System.out.println("第一次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
		
		taker.setMemento(emp.memento()); //备忘一次
		
		emp.setAge(38);
		emp.setEname("李四");
		emp.setSalary(9000);
		System.out.println("第二次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
		
		emp.recovery(taker.getMemento());//恢复到备忘录保存的状态
		System.out.println("第三次打印对象:"+emp.getEname()+"----"+emp.getAge()+"----"+emp.getSalary());
	}
}
--运行结果:
第一次打印对象:张三----18----900.0
第二次打印对象:李四----38----9000.0
第三次打印对象:张三----18----900.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值