Day9设计模式(代理模式、桥接模式、外观模式、享元模式、装饰者模式、组合模式、模板方法模式)总结

1、代理模式

为什么要有代理模式?
代理模式能够增强本类的方法。可以通过三种方式来完成代理模式

①静态代理:其实就是把需要被代理的类聚合到对应的代理类。本类实现接口,然后聚合到代理类。代理类构造方法接收被代理类,并且开启一个方法增强代理方法。

问题:代理类也需要实现本类的同一个接口,如果需要很多代理的类,那么就会发生类爆炸的问题

代码
接口

public interface ITeacherDao {
    void teach();
}

被代理类

public class TeacherDao implements ITeacherDao{

	@Override
	public void teach() {
		System.out.println("教授课程");
	}

}

②动态代理:其实就是在内存的时候动态创建代理类,原理就是利用反射获取被代理类的信息。好处就是不需要实现接口,可以通过一个固定的代理工厂来处理这些代理类创建。工厂类需要接受被代理类对象,反射获取属性。

代理类工厂

public class ProxyFactory {
	//维护的对象
	Object target;

	public ProxyFactory(Object target) {
		this.target=target;
	}
	
	public Object getProxyInstance() {
		return Proxy.newProxyInstance(target.getClass().getClassLoader()
				, target.getClass().getInterfaces()
				,
				new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("JDK动态代理方法");
						// 对象的方法。
						method.invoke(target, args);
						System.out.println("执行结束");
						return null;
					}
				});
	}
}

③Cglib:主要是处理那些没有实现接口但是仍然想增强方法的类。原理就是创建这个类的子类,重写这个代理方法。同样也是要保管一个被代理对象到代理工厂类上,而且需要实现对应接口和方法。

public class ProxyFactory implements MethodInterceptor{
	
	Object target;
	
	public ProxyFactory(Object target) {
		this.target=target;
	}
	
	public Object getProxyInstance() {
		//1.工具类
		Enhancer enhancer=new Enhancer();
		//2.设置父类
		enhancer.setSuperclass(target.getClass());
		//3.回调函数
		enhancer.setCallback(this);
		//4.创建子类
		return enhancer.create();
	}

	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
		System.out.println("Cglib ");
		Object invoke = method.invoke(target, arg2);
		System.out.println("结束");
		return invoke;
	}

}

2.桥接模式

为什么要有桥接模式?
为了分开抽象类和行为接口类。好处就是能够方便类的拓展,抽象类和接口类就像一座桥一样,每次需要用到什么类就可以直接通过抽象这一层来寻找。主要可以解决,手机品牌,样式等组合比较多的。品牌的call方法不同,这就是行为接口类,样式就是抽象类。使用桥接模式的关键就是区分好抽象与行为。

桥接模式的四种角色
①抽象类
②抽象类的具体实现类
③行为接口
④行为接口实现类
这样的划分好处就是无论拓展抽象类这层还是接口行为类这层都可以快速拓展,而且不影响客户端。也就是他们分开了两层抽象和行为。

在这里插入图片描述

实例:JDBC源码下面的Connection可以通过DriverManager的判断,决定使用哪一个connection相当于就是行为接口。而Manager就是一个具体实现类(而且也充当抽象类)。如果Connection要拓展只需要实现Connection接口就可以了。

3、外观模式

为什么要有外观模式?
比如现在要处理电影开播,是不是要处理屏幕、声响、爆米花等的开关和播放?如果是客户端直接调用这些类的方法,万一某个设备发生改变,或者方法拓展,客户端都需要进行修改,违反ocp原则。那么解决的方法最好就是有一个类可以专门处理这些流程,无论子系统类如何修改最后客户端只需要调用类的固定方法就可以了。那么就可以用到外观模式,想当于就是一个界面类,里面聚合了所有的子系统类,比如屏幕、声响,并且根据需要创建方法,把这些子系统类的方法调用排好序,做好流程调用。

外观类

public class HomeTheaterFacade {
	private DVDPlayer dvdPlayer;
	private Popcorn popcorn;
	private Projector projector;
	
	private Screen screen;
	
	private TheaterLight theaterLight;
	
	private Stereo stereo;
	
	
	public HomeTheaterFacade() {
		dvdPlayer=DVDPlayer.getInstance();
		popcorn=Popcorn.getInstance();
		projector=Projector.getInstance();
		screen=Screen.getInstance();
		theaterLight=TheaterLight.getInstance();
		
		stereo=Stereo.getInstance();
	}
	
	public void ready() {
		popcorn.on();
		popcorn.pop();
		screen.down();
		stereo.on();
		projector.on();
		dvdPlayer.on();
	}
	
	public void play() {
		dvdPlayer.play();
	}
	
	public void off() {
		dvdPlayer.plased();
		dvdPlayer.off();
		screen.up();
		stereo.off();
		popcorn.off();
	}

}

在这里插入图片描述

具体的实例:Mybatis的Configuration,很多子系统类Factory组合到里面去,并且调用newMetaObject方法根据Factory返回对应的MetaObject。其中会调用到这些Factory的方法,并形成流程执行。

在这里插入图片描述

4、享元模式

为什么要有享元模式?
原因就是一个对象如果需要重复使用,如果我们不停创建就会造成内存的浪费。比如一个网站里面大部分对象和元素需要重复使用,那么这个使用就可以共享这些对象和元素。通过一个池。而享元模式就是通通过一个池来保存这些对象,这些对象共同点就是有内部状态,用于区分是否需要存入池中。如果没有才存储。

享元模式的内外部状态解释:
①外部状态:就是相当于是五子棋的坐标,对象的标识
②内部状态:五子棋的颜色,黑白。是不是无论有多少个五子棋都会只分为2种放入池中,那么两个对象就可以存入池中

享元模式的角色
①FlyWeight:抽象享元类,定义外部和内部状态
②ConcreteFlyWeight:具体享元类,实现对应的抽象方法
③UsharedFlyWeight:不共享的享元,不放入池中
④工厂类:也就是池子,提供获取共享对象方法

factory

public class WebSiteFactory {
	
	private static Map<String,ConcreteWebSite> map=new HashMap<String, ConcreteWebSite>();
	
	public static ConcreteWebSite  getWebSite(String type) {
		if(map.containsKey(type)) {
			return map.get(type);
		}else {
			map.put(type, new ConcreteWebSite(type));
			return map.get(type);
		}
		
		
	}
	
	public static int getSize() {
		return map.size();
	}

}

外部状态(独立一个类,导致享元模式更复杂)

public class User {
	
	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

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

}

具体享元类

public class ConcreteWebSite extends WebSite{
    public ConcreteWebSite(String type) {
    	setType(type);
    }

	@Override
	public void use(User user) {
		System.out.println("网站的类型是:"+type+"  ,网站的使用者是"+user.getName());
		
	}
}

抽象享元类

public abstract class WebSite {
	
	String type="";
	
	public abstract void  use(User user);

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}
	
	

}

在这里插入图片描述

5.装饰者模式

为什么要有装饰者模式?
现在有一个需求就是买一杯饮料和加入各种配料。正常做法就是创建各种类并且有各种组合。第二种就是饮料抽象类里面配置了配料。第一种的问题就是类爆炸,第二种就是配料修改麻烦。所以要用到装饰者模式。其实就是饮料是主体,各种配料就是辅助。每次加入一种配料,那么就用原来那杯饮料(加上配料的)聚合到新创建的配料类里面。这么说可能有点难懂,代码会好懂一些。

装饰者模式的角色
①抽象类:也就是饮料和配料的父类
②继承抽象类的饮料类
③继承抽象类的配料类,也就是Decorator

Drink(抽象类)

public abstract class Drink {
	
	private String des;
	
	private float price=0.0f;

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}

	public float getPrice() {
		return price;
	}

	public void setPrice(float price) {
		this.price = price;
	}
	
	public abstract float cost();
	

}

Coffee(其中一种品种的饮料继承抽象类,主要实现cost方法)

public class Coffee extends Drink{

	@Override
	public float cost() {
		
		return super.getPrice();
	}

}

Coffee继承类(设定好具体价和名称。)

public class ShortCoffee extends Coffee{
	
	public ShortCoffee() {
		super.setDes("shortcoffee");
		super.setPrice(7.0f);
	}

}

Decorator(聚合Drink后也就是被修饰者,就能够通过方法调用来处理他们的总共价格以及说明)

public class Decorator extends Drink{
	
	Drink drink;
	
	public Decorator(Drink drink) {
		this.drink=drink;
	}

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		//当前装饰者价钱加上饮料的所有价格
		return super.getPrice()+drink.cost();
	}

	@Override
	public String getDes() {
		// TODO Auto-generated method stub
		return super.getDes()+"  价格是:"+super.getPrice()+" & "+drink.getDes();
	}
	
	
	
	
	

}

Decorator具体类

public class Chocolate extends Decorator{

	public Chocolate(Drink drink) {
		super(drink);
		super.setPrice(5.0f);
		super.setDes("一杯巧克力");
	}

}
public class Milk extends Decorator{

	public Milk(Drink drink) {
		super(drink);
		super.setPrice(3.0f);
		super.setDes("一杯牛奶");
	}

}

在这里插入图片描述

6.组合模式

为什么要用到组合模式?
为了解决树形结构问题,也就是大学里面有很多学院,学院下有很多专业的管理

组合模式的角色
①叶子节点
②Component:管理子部件,对象声明接口,大家都共用这个接口
③Composite:存储子部件,实现共用方法

简单来说就是Component定义了子部件的add和remove等方法,Composite来实现这些方法,每个Composite的处理方法add或remove可能不相同。叶子节点通常不需要实现方法,比如专业。其实就是A是B的子部件,那么A就通过list的泛型聚合到B上,B是C的子部件,B也用同样方式聚合到C上。

在这里插入图片描述

Component

public abstract class OrganizationComponent {
	
	private String  name;
	
	private String des;
	
	public void add(OrganizationComponent organizationComponent) {
		throw new  UnsupportedOperationException();
	}
	
	

	public void remove(OrganizationComponent organizationComponent) {
		throw new  UnsupportedOperationException();
	}
	
	public abstract void print();
	
	

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDes() {
		return des;
	}

	public void setDes(String des) {
		this.des = des;
	}
	
	/**
	 * @param name
	 * @param des
	 */
	public OrganizationComponent(String name, String des) {
		super();
		this.name = name;
		this.des = des;
	}
	
	

}

University(Composite)

public class University extends OrganizationComponent{
	
	List<OrganizationComponent> list=new ArrayList<OrganizationComponent>();
	
	public University(String name,String des) {
		super(name, des);
	}
	
	@Override
	public void add(OrganizationComponent organizationComponent) {
		list.add(organizationComponent);
	}
	
	@Override
	public void remove(OrganizationComponent organizationComponent) {
		list.remove(organizationComponent);
	}

	@Override
	public void print() {
		System.out.println("--------"+this.getName()+"--------");
		
		for(OrganizationComponent organizationComponent:list) {
			organizationComponent.print();
		}
		
	}

}

College(Composite)

public class College extends OrganizationComponent{
	
	List<OrganizationComponent> list=new ArrayList<OrganizationComponent>();
	
	public College(String name,String des) {
		super(name, des);
	}
	
	@Override
	public void add(OrganizationComponent organizationComponent) {
		list.add(organizationComponent);
	}
	
	@Override
	public void remove(OrganizationComponent organizationComponent) {
		list.remove(organizationComponent);
	}

	@Override
	public void print() {
		System.out.println("--------"+this.getName()+"--------");
		
		for(OrganizationComponent organizationComponent:list) {
			organizationComponent.print();
		}
		
	}

}

Department

public class Client {
	public static void main(String[] args) {
		University qingHuaUniversity=new University("清华大学","中国第一学府");
		
		College college=new College("计算机学院", "好学员");
		College college2=new College("通信学院", "通信好");
		
		college.add(new Department("计算机与科学", "1"));
		college.add(new Department("软件工程", "好"));
		
		college2.add(new Department("通信工程", "1"));
		
		qingHuaUniversity.add(college);
		qingHuaUniversity.add(college2);
		
		qingHuaUniversity.print();
		
		
	}
}

Client

public class Client {
	public static void main(String[] args) {
		University qingHuaUniversity=new University("清华大学","中国第一学府");
		
		College college=new College("计算机学院", "好学员");
		College college2=new College("通信学院", "通信好");
		
		college.add(new Department("计算机与科学", "1"));
		college.add(new Department("软件工程", "好"));
		
		college2.add(new Department("通信工程", "1"));
		
		qingHuaUniversity.add(college);
		qingHuaUniversity.add(college2);
		
		qingHuaUniversity.print();
		
		
	}
}

7.模板方法模式

为什么要有模板方法模式?
原因就是固定流程的方法,可以通过模板方法来完成对应流程调用

模板方法角色
①抽象类:定义模板方法和抽象方法
②具体实现类:主要就是实现抽象方法。
比如豆浆有很多品种,他们制作流程一直,但是add配料不同,那么抽象类豆浆就定义add抽象方法,让RedBeanSoyaMilk继承SoyaMilk并且实现抽象方法,并且调用模板方法make就能够处理固定的select,add,soak,beat流程处理。

在这里插入图片描述

SoyaMilk(抽象类)

public abstract class SoyaMilk {
	
	final void make() {
		select();
		add();
		soak();
		beat();
	}
	
	public void select() {
		System.out.println("选择黄豆");
	}
	
	public abstract void add();
	
	public void soak() {
		System.out.println("浸泡黄豆");
	}
	
	public void beat() {
		System.out.println("打碎黄豆");
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式组合模式外观模式享元模式代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值