常见结构型设计模式


参考: 地址
动态代理详见: 动态代理Spring AOP


适配器模式

适配器模式,把一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。也是一种包装类,与装饰模式同样具有包装的功能。

优缺点
优点:

  1. 可以让任何两个没有关联的类一起允许
  2. 提高了类的复用,即使该类的接口标准不符合系统需要,而通过适配器就可以使用

缺点:

  1. 过多的使用会导致系统凌乱

适用场景

  1. 想使用一个已存在的类,而其接口不符合需求
  2. 需要创建一个可重用的类,即与接口无关的类

模式的应用

  1. JDK 中的 IO 库大量使用了适配器模式,如 ByteArrayInputStream(ByteArrayOutputStream)适配器类实现了 InputStream 接口,将一个 byte 数组的接口适配成 InputStream 流处理器的接口;还有 FileOutputStream、Reader等。
  2. Spring 的 AOP 不同Advice类型和对应的拦截器之间

角色分配

  1. 目标接口
  2. 被适配者(已有的目标接口实现类)
  3. 适配者
  4. 适配器

适配器模式的实现

1.目标接口

		interface Target{
			void connection();
		}

2.被适配者

		class Typec implements Target{
			public void connection(){
				System.out.println("使用Type-c数据线连接...");
			}
		}

3.适配者

		class Micro{
			public void connection(){
				System.out.println("使用Micro USB数据线连接...");
			}
		}

4.适配器
(1)类适配器(继承被适配类,同时实现标准接口)

		class TypecAdapter extends Micro implements Target{
			public void connection(){
				System.out.println("使用转接头...");
				super.connection();//调用父类的方法
			}
		}

(2)对象适配器

		class TypecAdapter implements Target{
			private Target target;
			public TypecAdapter(Target target){
				this.target = target;
			}
			public void connection(){
				System.out.println("使用转接头...");
				target.connection();
			}
		}

区别
类适配器:对象继承的方式,静态定义
对象适配器:对象组合的方法

5.使用
(1)使用类适配器

		//原功能
		Target target = new Typec();
		target.connection();
		//适配后功能
		Target adapter = new TypecAdapter();
		adapter.connection();

(2)使用对象适配器

		Target adapter = new TypecAdapter(new Micro());
		adapter.connection();

注:尽量使用对象的适配器模式,少用继承的同时,不能过度使用适配器模式


组合模式

组合模式,将对象组合成树形结构以表示部分以及整体的层次结构,使得我们对单个对象和组合对象的使用具有一致性。

优缺点
优点:

  1. 高层模块调用简单
  2. 节点自由增加

缺点:

  1. 子叶和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则

适用场景
需求中需要体现部分与整体层次结构的时候,如树形菜单,文件、文件夹的管理

角色分配

  1. 抽象/接口类
  2. 具体树枝类
  3. 具体树叶类(都实现抽象类)

组合模式的实现

1.抽象类

		public abstract Employee{
			private String name;
			private String dept;
			public Employee(String name,String dept){
				this.name = name;
				this.dept = dept;
			}
			public abstract void add(Employee e);
			public abstract void print();
		}

2.具体树枝类,老板类

		public Boss extends Employee{
			private List<Employee> temp = new ArrayList<Employee>();
			public Boos(String name,String dept){
				super(name,dept);
			}
			public void add(Employee e){
				temp.add(e);
			}
			public void print(int depth){
				System.out.println("第"+depth+"级职员:"+name)
				for(Employee e : temp){
					e.print(depth+1);
				}
			}
		}

3.具体树叶类,员工

		public Staff extends Employee{
			public Staff(String name,String dept){
				super(name,dept);
			}
			public void add(Employee e){}
			public void print(int depth){
				System.out.println("""+depth+"级职员:"+name")
			}
		}

4.使用

		Employee boss = new Boss("MOKE","Boss")
		boss.add(new Boss("Robert","CEO"));
		boos.add(new Boss("John","CEO");)
		CEO1.add(new Staff("Laura","Marketing"));
		CEO2.add(new Staff("Bob","Marketing"));

装饰者模式

装饰者模式,以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

优点

  1. 相比继承更加的灵活,允许动态增加或删除一个装饰的功能。

角色分配

  1. 抽象构件角色
  2. 具体构件角色
  3. 装饰角色(持有抽象构件角色的实例)
  4. 具体装饰角色

装饰者模式的实现

1.抽象构建角色

		interface Student{
			public void study();
		}

2.具体构件角色

		class MOKE implements Student{
			public void study(){
				System.out.println("开始学习...")}
		}

3.装饰角色

		class Decorator implements Student{
			private  Student stu;
			public Decorator(People people){
				this.people = people;
			}
			public void study(){
				stu.study();
			}
		}

4.具体装饰角色

		class MathDecorator extends Decorator{
			public MathDecorator(Student stu){
				super(stu);
			}
			public void study(){
				super.study();
				System.out.println("学习数学");
			}
		}

		class ComputerDecorator extends Decorator{
			public ComputerDecorator(Student stu){
				super(stu);
			}
			public void study(){
				super.study();
				System.out.println("学习计算机");
			}
		}

5.使用

		MOKE p = new MathDecorator(new ComputerDecorator(new MOKE()));//声明变量要尽量使用顶层的超类
		p.study();
		/*
		开始学习...
		学习计算机
		学习数学
		*/

简单装饰者模式

1.只有一个具体构件角色:可以去掉抽象构件角色

		class Decorator extends MOKE{//直接继承具体构件角色
			private  Student stu;
			public Decorator(People people){
				this.people = people;
			}
			public void study(){
				stu.study();
			}
		}

2.只有一个装饰角色(多个具体构件角色):可以去掉装饰角色

		class MathDecorator implements Student{//直接实现抽象构件
			private Student student;
			public MathDecorator(Student stu){
				this.student = stu
			}
			public void study(){
				student.study();
				System.out.println("学习数学");
			}
		}

3.具体构件角色和具体装饰角色只有一个:继承形式

半透明装饰者模式

在实现抽象构件的装饰角色中,定义了新的方法

		class MathDecorator extends Decorator{
			public MathDecorator(Student stu){
				super(stu);
			}
			public void study(){
				super.study();
				System.out.println("学习数学");
			}
			public void eat(){				System.out.println("学完数学,食堂吃饭");
			}
		}

使用:

		MathDecorator mathdecorator = new MathDecorator(new ComputerDecorator(new MOKE()));//生成顶层超类,调用eat会出错,需要向下转型,所以直接使用子类
		mathdecorator.study();
		mathdecorator.eat();

外观模式

外观模式,为子系统中的一组接口提供了一个统一的访问接口,这个接口使得子系统更容易被访问或者使用。

优点

  1. 客户端与子系统直接解耦,便于子系统的扩展与维护
  2. 客户端不需要知道子系统内部实现就可以使用
  3. 子系统能更好的划分对内对外提供的不同功能

适用场景
4. 为复杂的模块提供外界访问的模块
5. 在层析结构中,可以定义每一层的入口

角色分配
6. 子系统角色(多、复杂)
7. 门面角色
8. 客户角色(通过门面角色操作子系统)

外观模式的实现

1.子系统角色(多个模块)
(1)cpu

		public class CPU{
			public void start(){
				System.out.println("CPU is running...");
			}
			public void shutDown(){
				System.out.println("CPU is shutDown...");
			}
		}

(2)Disk

		public class Disk{
			public void start(){
				System.out.println("Disk is running...");
			}
			public void shutDown(){
				System.out.println("Disk is shutDown...");
			}
		}

2.门面角色

		public class Computer{
			private CPU cpu;
			private Disk disk;
			public Computer(){
				cpu = new CPU();
				disk = new Disk();
			}
			public void start(){
				System.out.println("Computer starting...");
				cpu.start();
				disk.start();
				System.out.println("Computer had started.");
			}
			public void shutDown(){
				System.out.println("Computer ending...");
				cpu.shutDown();
				disk.shutDown();
				System.out.println("Computer had shutDown");
			}
		}

3.客户角色(使用)

		public class Cilent{
			public static void mian(String[] args){
				Computer computer = new Computer();
				computer.start();
				System.out.println("==========");
				computer.shutDown();
			}
		}

代理模式

外观模式是对子系统中多个类的封装,而代理模式是代理一个类,即对一个类的封装。真正的业务功能还是由目标类来实现,代理类只是用于扩展、增强目标类的行为。

静态代理和动态代理区别

  1. 静态代理:手写或工具生成代理类,在程序运行前就已经编译好了
  2. 动态代理:在程序运行期间根据需要动态创建代理类和实例

应用

  1. Spring的AOP
  2. Mybatis缓存机制对连接池的管理

角色分配

  1. 抽象角色
  2. 被代理角色(抽象角色实现类)
  3. 代理角色
  4. 客户端

代理模式的实现

静态代理

1.抽象角色

		public interface Movie{
			void play();
		}

2.被代理角色

		public class RealMovie implements Movie{
			public void play(){
				System.out.println("正在放映:惊奇队长");
			}
		}

3.静态代理角色

		public class Cinema implements Movie{
			RealMovie movie;
			public Cinema(RealMovie movie){
				this.movic = movie;
			}
			public void play(){
				advertisement(true);//前置增强
				movie.play();//具体功能,委托目标类
				advertisement(false);//后置增强
			}
			public void advertisement(boolean playing)
				if(playing)
					System.out.println("电影快要开始了,请自备3D眼镜");
				else
					System.out.println("电影已经结束,请检查随身物品");
		}

4.客户端(使用)

		Movie realmovie = new RealMovie();
		Movie movie = new Cinema(realmovie);
		movie.play();
动态代理

相关接口和类:InvocationHandler(Interface)接口和Proxy(Class)类
1.抽象角色、被代理角色(同上)
2.动态代理角色

		public class Cinema implements InvocationHandler{
			private Object proxied;
			public ProxyHandler(Object proxied){
				this.proxied = proxied;
			}
			public Object invoke(Object proxy,Method,Object[] args) throws Throwable{
				System.out.println("电影快要开始了,请自备3D眼镜");
				Object obj = method.invoke(proxied, args);
				System.out.println("电影已经结束,请检查随身物品");
			}
		}

3.客户端(使用)

		Movie realmovie = new RealMovie();
		Movie proxyMovic = Proxy.newProxyInstance(Movie.class.getClassLoader(),new Class[] {Movie.class},new ProxyHandler(realmovie ));
		//三大参数:实例对象,实例方法,实例方法的参数
		proxyMovic.play();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值