1.桥接模式 bridge(抽象类的实现的子类,通过聚合间接调用接口方法 就是桥)
- 实现和抽象分开,使他可以独立改变
- 结构型设计模式
- 基于类的最小设计原则(增加功能,增加最少个数的类),通过封装 聚合和继承让不同类实现不同职责
图 23桥接模式原理图
图 26桥接模式传统解决手机操作问题
图 24桥接模式解决手机操作问题
图 27桥接模式代码结构
--------传统方式实现,需要先实现后继承------
public interface Phone {
void open();
void call();
void close();
}
public class Folded implements Phone {
@Override
public void open() {
System.out.println("折叠手机开机");
}
@Override
public void call() {
System.out.println("折叠手机打电话");
}
@Override
public void close() {
System.out.println("折叠手机关机");
}
}
public class VIVOFold extends Folded {
public void open() {
super.open();
System.out.println("VIVO手机开机");
}
public void call() {
super.call();
System.out.println("VIVO手机打电话");
}
public void close() {
super.close();
System.out.println("VIVO手机关机");
}
}
public class XIAOMIFold extends Folded {
@Override
public void open() {
super.open();
System.out.println("小米手机开机");
}
@Override
public void call() {
super.call();
System.out.println("小米手机打电话");
}
@Override
public void close() {
super.close();
System.out.println("小米手机关机");
}
}
public class UpRight implements Phone {
@Override
public void open() {
System.out.println("直立手机开机");
}
@Override
public void call() {
System.out.println("直立手机打电话");
}
@Override
public void close() {
System.out.println("直立手机关机");
}
}
public class VIVOUpRight extends UpRight {
public void open() {
super.open();
System.out.println("VIVO手机开机");
}
public void call() {
super.call();
System.out.println("VIVO手机打电话");
}
public void close() {
super.close();
System.out.println("VIVO手机关机");
}
}
public class XIAOMIUpRight extends UpRight {
@Override
public void open() {
super.open();
System.out.println("小米手机开机");
}
@Override
public void call() {
super.call();
System.out.println("小米手机打电话");
}
@Override
public void close() {
super.close();
System.out.println("小米手机关机");
}
}
//测试类
public class Client {
public static void main(String[] args) {
Phone phone=new VIVOFold();
phone.open();
phone.call();;
phone.close();
System.out.println("--------------");
Phone phone1=new XIAOMIFold();
phone1.open();
phone1.call();;
phone1.close();
System.out.println("--------------");
Phone phone2=new XIAOMIUpRight();
phone2.open();
phone2.call();;
phone2.close();
}
}
---改进的代码----------
//1. 写桥接接口 子类实现接口
public interface BrandBridge {
void open();
void call();
void close();
}
public class Vivo implements BrandBridge {
@Override
public void open() {
System.out.println("vivo打开手机");
}
@Override
public void call() {
System.out.println("vivo打电话");
}
@Override
public void close() {
System.out.println("vivo关闭手机");
}
}
public class XiaoMi implements BrandBridge {
@Override
public void open() {
System.out.println("xiaomi打开手机");
}
@Override
public void call() {
System.out.println("xiaomi打电话");
}
@Override
public void close() {
System.out.println("xiaomi关闭手机");
}
}
//2.再写手机类, 聚合桥接类,写继承的手机子类
public class Phone {
BrandBridge brand;
Phone(BrandBridge brand){
this.brand=brand;
}
void open(){
brand.open();
}
void call(){
brand.call();
}
void close(){
brand.close();
}
}
public class FoldedPhone extends Phone {
public FoldedPhone(BrandBridge brand) {
super(brand);
}
public void open(){
System.out.println("折叠手机");
super.open();
}
public void call(){
System.out.println("折叠手机");
super.call();
}
public void close(){
System.out.println("折叠手机");
super.close();
}
}
//设计模式好不好用主要看客户端调用方便
public class Client {
public static void main(String[] args) {
FoldedPhone foldedPhone = new FoldedPhone(new Vivo());
foldedPhone.open();
foldedPhone.call();
foldedPhone.close();
System.out.println("====================");
UpRightPhone upRightPhone = new UpRightPhone(new XiaoMi());
upRightPhone.open();
upRightPhone.call();
upRightPhone.close();
}
}
//总结: 如果我想一个类拓展性好, 那我先写桥接接口 再子类实现
//然后写个这个类聚合,然后子类调用桥接类方法,
//一句话: 逆序写代码…
2.桥接模式在JDBC的应用(与标准的有出入)
图 25桥接模式在JDBC源码分析 DriverManager是桥接类(不变的部分),(增加的部分是) ConnectionImpl …Oracle…
1.调用了getConnection方法返回Connection对象
Class.forName("com.mysql.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jams", "root", "root");
//源代码 getConnection()方法
@CallerSensitive
public static Connection getConnection(String url,
String user, String password) throws SQLException {
java.util.Properties info = new java.util.Properties();
if (user != null) {
info.put("user", user);
}
if (password != null) {
info.put("password", password);
}
return (getConnection(url, info, Reflection.getCallerClass()));
}
//往里面找
// Worker method called by the public getConnection() methods.
private static Connection getConnection(
String url, java.util.Properties info, Class<?> caller) throws SQLException {
ClassLoader callerCL = caller != null ? caller.getClassLoader() : null;
synchronized(DriverManager.class) {
// synchronize loading of the correct classloader.
if (callerCL == null) {
callerCL = Thread.currentThread().getContextClassLoader();
}
}
if(url == null) {
throw new SQLException("The url cannot be null", "08001");
}
println("DriverManager.getConnection(\"" + url + "\")");
// Walk through the loaded registeredDrivers attempting to make a connection.
// Remember the first exception that gets raised so we can reraise it.
SQLException reason = null;
for(DriverInfo aDriver : registeredDrivers) { //我认为这里可能使用了桥接模式,寻找对应的驱动,找到mysql驱动返回
// If the caller does not have permission to load the driver then
// skip it.
if(isDriverAllowed(aDriver.driver, callerCL)) {
try {
println(" trying " + aDriver.driver.getClass().getName());
Connection con = aDriver.driver.connect(url, info); //这里调用了Driver类实际上调用了DriverManager的 DriverManager.registerDriver(new Driver());,桥接了DriverManager
//他的这个聚合直接使用静态类实现....
if (con != null) {
// Success!
println("getConnection returning " + aDriver.driver.getClass().getName());
return (con);
}
} catch (SQLException ex) {
if (reason == null) {
reason = ex;
}
}
} else {
println(" skipping: " + aDriver.getClass().getName());
}
}
// if we got here nobody could connect.
if (reason != null) {
println("getConnection failed: " + reason);
throw reason;
}
println("getConnection: no suitable driver found for "+ url);
throw new SQLException("No suitable driver found for "+ url, "08001");
}
//aDriver.driver.connect(url, info); 方法有DriverManager
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
//public class NonRegisteringDriver implements Driver的类中
public Connection connect(String url, Properties info) throws SQLException {
if (url != null) {
if (StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:loadbalance://")) {
return this.connectLoadBalanced(url, info);
}
if (StringUtils.startsWithIgnoreCase(url, "jdbc:mysql:replication://")) {
return this.connectReplicationConnection(url, info);
}
}
Properties props = null;
if ((props = this.parseURL(url, info)) == null) {
return null;
} else {
try {
com.mysql.jdbc.Connection newConn = ConnectionImpl.getInstance(this.host(props), this.port(props), props, this.database(props), url); //ConnectionImpl其实是Mysql连接的类,没有注册过类,则默认注册mysql
return newConn;
} catch (SQLException var6) {
throw var6;
} catch (Exception var7) {
SQLException sqlEx = SQLError.createSQLException(Messages.getString("NonRegisteringDriver.17") + var7.toString() + Messages.getString("NonRegisteringDriver.18"), "08001");
sqlEx.initCause(var7);
throw sqlEx;
}
}
}
//总结: 1.如何学会看源代码 ,先看类的头部关系画uml类图(一个一个点进去,逐步画类 然后找类和类的关系),然后debug调试运行过程
3.优缺点
- 提高系统灵活性.帮助系统分层设计
- 桥接替代多层继承,可以减少类爆炸问题,减低系统维护成本
- 增加系统理解难度
- 要正确区分系统独立变化的2个维度(抽象和实现)
4.应用场景(一句话,代码需要增加分类功能 可以采用聚合调用聚合的方法)
- jdbc驱动
- 银行转账 普通用户(抽象 不变) 和网上转账(实现 后期增加的)
- 消息分类 消息类型:即时消息和延时消息(抽象) 消息分类: 数据短信 QQ消息(实现)
5.装饰者模式(工作常用)
图28装饰者模式原理图
图31装饰者模式星巴克咖啡传统
- 星巴克咖啡订单问题(计算不同搭配的钱/单品咖啡)导致类爆炸(排列组合实现cost方法)
- 改进为装饰者(使用非常方便,并且只加一个类就可以与其他类组合) 满足ocp原则
图 29装饰者模式星巴克咖啡改进
Drink coffee=new Coffee(); coffee.cost();//计算多少钱 Drink add=new Chocolate(coffee); add.cost(); //计算咖啡和巧克力的全部费用 像打包一个快递 :主体(Component) 衣服 陶瓷 被装饰者 包装(Decorator) 泡沫 木板 装饰者(递归加上价格)
-----全部代码-------
//全部方法和成员由父类创建 继承给子类调用
//1.创建抽象类
public abstract class Drink {
private String desciption;
private float price;
public String getDesciption() {
return desciption;
}
public void setDesciption(String desciption) {
this.desciption = desciption;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
//2.继承抽象类
public class Coffee extends Drink{
}
//3.创建子类
public class Decaf extends Coffee {
public Decaf(){
setDesciption("Decaf");
setPrice(9.0f);
}
}
public class ShortBlack extends Coffee {
ShortBlack(){
setDesciption("ShortBlack");
setPrice(10.0f);
}
}
//4.创建装饰者类 继承和组合 被装饰者类 !!!
public class Decorator extends Drink {
Drink obj;
Decorator(Drink obj){
this.obj=obj;
}
}
//5.创建装饰者的子类
public class Chocolate extends Decorator{
public Chocolate(Drink obj) {
super(obj);
setDesciption(obj.getDesciption()+"巧克力");
setPrice(obj.getPrice()+3.0f);
}
}
public class Milk extends Decorator{
Milk(Drink obj) {
super(obj);
setDesciption(obj.getDesciption()+"牛奶");
setPrice(obj.getPrice()+2.0f);
}
}
//测试类
public class Client {
public static void main(String[] args) {
Drink decaf = new Decaf();
Drink chocolate = new Chocolate(decaf);
Drink chocolate1 = new Chocolate(chocolate);
float cost = chocolate1.getPrice();
System.out.println(cost); //会得到全部加入购物车饮料的总钱数
System.out.println(chocolate1.getDesciption());
}
}
6.装饰者在JDK IO流的应用 InputStream(被装饰者)的FilterInputStream相当于(装饰者),下面的DataInputStream也继承
30装饰者模式jdkio源码原理图
//核心代码装饰者类继承和组合父类
public
class FilterInputStream extends InputStream { //继承父类 和 DataInputStream同级
/**
* The input stream to be filtered.
*/
protected volatile InputStream in; //装饰父类 构造方法也是传入这个
//测试代码,子类的子类可以把父类组合到类内,这样的形式可能是装饰者模式
DataInputStream dis = new DataInputStream(new FileInputStream("d:\\1.txt"));
DataInputStream dis1 = new DataInputStream(dis);
//之前我就好奇为什么要把自己作为参数传给自己,原来是使用了装饰者
System.out.println(dis1.read());
dis.close();
7.组合模式(部分整体模式) 解决继承难以管理,树型结构组合对象,需要对象间有共同的功能
图组合32 33
1.几个概念
所有 整体和部分类继承 component(可以是接口/抽象类)然后实现他的 add() remove() print()方法空实现,方便管理,leaf是实现基础的get set方法
//传统的学校院系问题 学校 继承 学院 继承 院系 方便管理
----所有代码-----
//先写一个抽象类或接口,定义好整颗树,通用的方法
public abstract class Component {
private String name; // 名字
private String des; // 说明
Component(String name,String des){
this.name = name;
this.des = des;
}
void add(Component component){
throw new UnsupportedOperationException();
};
void remove(Component component){
throw new UnsupportedOperationException();
}
void print(){
throw new UnsupportedOperationException();
}
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;
}
}
//每一层的树都继承 组件,使用list存放他的孩子
public class University extends Component{
List<Component> components=new ArrayList<Component>();
University(String name, String des) {
super(name, des);
}
void add(Component component){
components.add(component);
};
void remove(Component component){
components.remove(component);
}
void print(){
System.out.println("--------------" + getName() + "--------------");
for (Component component : components) {
component.print();
}
}
}
public class College extends Component {
List<Component> components=new ArrayList<Component>();
College(String name, String res) {
super(name, res);
}
void add(Component component){
components.add(component);
};
void remove(Component component){
components.remove(component);
}
void print(){
System.out.println("--------------" + getName() +"--------------");
for (Component component : components) {
component.print();
}
}
}
//最后一层叶子不放东西,所以不用list存放数据
public class Department extends Component {
Department(String name,String res) {
super(name, res);
}
void print(){
System.out.println(getName()+getDes() );
}
public String getName() {
return super.getName();
}
public String getDes() {
return super.getDes();
}
}
//这才是设计模式的精髓,直接让代码富有逻辑性,可读性增强,写新代码也容易
public class Client {
public static void main(String[] args) {
University university = new University("清华大学","中国一流大学");
College college = new College("计算机学院", "计算机学院很好");
college.add(new Department("计算机科学与技术", "王牌专业"));
college.add(new Department("软件工程", "也是王牌专业"));
university.add(college);
College college1 = new College("财经学院", "财经很好");
college1.add(new Department("会计专业","都是金融人才"));
college1.add(new Department("金融工程专业","都是金融人才1"));
university.add(college1);
university.print();
}
}
//输出结果(非常简单)
--------------清华大学--------------
--------------计算机学院--------------
计算机科学与技术王牌专业
软件工程也是王牌专业
--------------财经学院--------------
会计专业都是金融人才
金融工程专业都是金融人才1
//删除一个专业,可以自己定义删除的代码细节
public class Client {
public static void main(String[] args) {
University university = new University("清华大学","中国一流大学");
College college = new College("计算机学院", "计算机学院很好");
Department department = new Department("计算机科学与技术", "王牌专业");
college.add(department);
college.add(new Department("软件工程", "也是王牌专业"));
college.remove(department);
university.add(college);
College college1 = new College("财经学院", "财经很好");
college1.add(new Department("会计专业","都是金融人才"));
college1.add(new Department("金融工程专业","都是金融人才1"));
university.add(college1);
university.print();
}
}
8.组合模式在HashMap的应用
Map是component HashMap是composite 有put putall方法
Node是hashMap的静态内部类(叶子节点的),实现Map 相当于 Leaf没有put putall方法
全部都实现了Map所以map是component
9.外观(界面)(过程facade)模式,就是封装类的思想,加一层类 来屏蔽子系统的调用 和简单工厂越看越像不同的是工厂是创建类的,而外观是调用不同功能的
外观类: 知道哪些子系统负责什么,给调用端的请求到子系统
子系统: 处理外观类给的任务,功能的实际提供者
- 传统方式实现影院系统 直接Client调用各个子系统 如图: 35外观模式解决传统问题
- 外观模式实现 创建影院设备类, (通过构造方法饿汉式初始化,分成多个阶段的方法调用的类) client调用外观类 如图 36外观模式
//客户端调用
public class Client {
public static void main(String[] args) {
Facade facade = new Facade();
facade.ready();
System.out.println("----------");
facade.stop();
}
}
//外观类 核心类
public class Facade {
private DVD dvd;
private Projector projector;
private Screen screen;
private Stere stere;
private Lighting lighting;
Facade(){
dvd=DVD.getInstance();
projector=Projector.getInstance();
screen=Screen.getInstance();
stere=Stere.getInstance();
lighting=Lighting.getInstance();
}
public void ready(){
screen.open();
lighting.stop();
projector.open();
stere.open();
dvd.play();
}
public void stop(){
dvd.stop();
stere.stop();
projector.close();
lighting.open();
screen.close();
}
}
//下面是子系统类
public class DVD {
private static DVD instance=new DVD();
public static DVD getInstance() {
return instance;
}
public void play(){
System.out.println("开启播放dvd");
}
public void stop(){
System.out.println("关闭dvd");
}
}
public class Lighting {
private static Lighting instance=new Lighting();
public static Lighting getInstance() {
return instance;
}
public void open(){
System.out.println("开灯");
}
public void stop(){
System.out.println("关灯");
}
}
public class Projector {
private static Projector instance=new Projector();
public static Projector getInstance() {
return instance;
}
public void open(){
System.out.println("开启投影仪");
}
public void close(){
System.out.println("关闭投影仪");
}
}
public class Screen {
private static Screen instance=new Screen();
public static Screen getInstance() {
return instance;
}
public void open(){
System.out.println("打开幕布");
}
public void close(){
System.out.println("关闭幕布");
}
}
public class Stere {
private static Stere instance=new Stere();
public static Stere getInstance() {
return instance;
}
public void open(){
System.out.println("开启立体声");
}
public void stop(){
System.out.println("关闭立体声");
}
}
10.外观模式在mybatis的应用
图 37.外观模式mybastis源码分析Configuration(外观类)的newMetaObject()方法
Configuration是外观类,子系统是DefaultObjectFactory DefaultObjectWrapperFactory DefaultReflectorFactory
import org.apache.ibatis.session.Configuration;
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory);
}
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
if (object == null) {
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory);
}
}
//到MetaObject类
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
11.外观模式的注意事项
- 降低客户端访问子系统复杂性(解耦)
- 用于系统太过复杂需要分层的时候
- 子系统太少了,不如直接使用,不用外观模式
- 维护遗留大项目 可以使用外观模式
12.享元(蝇量 flyweight)(共享对象)模式(开发用得多 string和池技术) 需求相似度高不要copy
- 解决的问题 38享元模式原理图
1. 避免重复对象内存浪费的问题,但是提供系统复杂度 s1=“aaa” 和new String(“aaa”);指向常量池的同一个位置
2. 解决网站外包复用问题,传统方案是复制粘贴定制修改- 4个角色
1. FlyWeight 抽象的享元角色,定义了对象的内部和外部状态的接口/实现
2. ConcreteFlyWeight 具体的享元角色,返回共享对象
3. UnSharedConcreteFlyWeight 不可共享的享元角色,一般不会出现在享元工厂里
4. FlyWeightFactory 享元工厂类,得到对象的方法 用集合HashMap/HashTable存放共享的对象,
3.内部和外部状态 (内部放在集合,外部构造器传进来)
内部: 不随环境改变的状态(对象内) 5子棋 棋的颜色
外部: 随环境改变的 5子棋 位置
----解决外包问题完整代码------
//抽象类
public abstract class WebSite {
abstract void use(User user);
}
//创建类
public class ConcreteWebSite extends WebSite {
String type=""; //内部状态
ConcreteWebSite(String type) {
this.type=type;
}
@Override
void use(User user) { //外部状态
System.out.println("网站类型为"+type+"正在被"+user.getName()+"使用");
}
}
//外部状态类
public class User {
private String name;
User(String name){
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//享元工厂类!!!,共享数据类
public class WebSiteFactory {
HashMap<String, ConcreteWebSite> pool=new HashMap<>();
public WebSite getWebSiteCategory(String type){
if(!pool.containsKey(type)){
pool.put(type,new ConcreteWebSite(type));
}
return (WebSite)pool.get(type);
}
int getCount(){
return pool.size();
}
}
//客户端调用测试发现有缓存的效果
//其实强智系统也可能使用了享元模式,一个强智系统由多个大学使用
public class Client {
public static void main(String[] args) {
WebSiteFactory webSiteFactory = new WebSiteFactory();
WebSite blog = webSiteFactory.getWebSiteCategory("博客"); //设置内部状态为博客(由我决定)
blog.use(new User("小明")); //外部状态为小明(由客户决定)
WebSite blog1 = webSiteFactory.getWebSiteCategory("博客");
blog1.use(new User("小叶"));
WebSite webSite = webSiteFactory.getWebSiteCategory("房地产");
webSite.use(new User("小李子"));
System.out.println(webSiteFactory.getCount());
}
}
//输出
网站类型为博客正在被小明使用
网站类型为博客正在被小叶使用
网站类型为房地产正在被小李子使用
2 //创建了2个网站,博客和房地产,重复创建的会直接返回
13.jdk里面Integer使用了享元模式
x=Integer.valueOf(127);// x==y -128到127使用享元模式,返回相同的对象,比new要快
y=Integer.valueOf(127);
public static Integer valueOf(int i) { //外部状态
if (i >= IntegerCache.low && i <= IntegerCache.high) //-128 到127 内部状态
return IntegerCache.cache[i + (-IntegerCache.low)]; //数组也是个集合 static final Integer cache[];
return new Integer(i);
}
14.代理(proxy)模式(替你做事,增强你的能力) 给对象(类)创建替身增强功能
- 解决的问题
1.动态增加对象的功能
2. 缺点 代理对象和被代理对象需要实现相同的接口,导致创建大量的代理对象,不好维护- 代理的对象可以是远程对象,创建开销大的对象,需要安全控制的对象
- 代理的分类
1.静态代理 需要类实现接口和聚合,有个代理类和被代理类
public interface Play {
void play();
}
//被代理类
public class PlayImpl implements Play{
@Override
public void play() {
System.out.println("被代理类的方法");
}
}
//代理类
public class PlayPoxy implements Play{
Play play;
public PlayPoxy(Play play){
this.play=play;
}
@Override
public void play() {
System.out.println("代理前");
play.play();
System.out.println("代理后");
}
}
public class Client {
public static void main(String[] args) {
PlayPoxy playPoxy = new PlayPoxy(new PlayImpl());
playPoxy.play();
}
}
2.动态代理(JDK代理) 使用jdk的方法, 传入一个接口 写个工厂
Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler(){ invoke方法的 returnVal=method.invoke(target,args); return returnVal;//可以没有,观察一下args})输出对象hashcode带有 $proxy说明是代理对象
public interface Play {
void play();
}
public class PlayImpl implements Play {
@Override
public void play() {
System.out.println("被代理类的方法");
}
}
public class PlayPoxy {
Object target;
public PlayPoxy(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 { //代理全部方法调用可用method的方法判断调用哪个方法
System.out.println("jdk动态代理前");
Object invoke = method.invoke(target, args);
System.out.println("jdk动态代理后");
return invoke;
}
});
}
}
public class Client {
public static void main(String[] args) {
Play target = new PlayImpl();
PlayPoxy playPoxy = new PlayPoxy(target);
Play proxyInstance = (Play)playPoxy.getProxyInstance();
proxyInstance.play();
}
}
3.Cglib动态代理 在内存创建单个对象,不需要实现接口和聚合 spring AOP的底层
//导入cglib的jar文件 ,代理类实现 MethodIntercepttor类的方法 intercept和jdk代理写法一样
- 不能为final/static会报错,不会拦截和执行业务方法
public class PlayImpl {
public int play() {
System.out.printl![请添加图片描述](https://img-blog.csdnimg.cn/a085daacf6a04548b588d5456fcdbe2a.png)
n("被代理类的方法"); return 1;
}
}
public class PlayPoxy implements MethodInterceptor {
private Object target;
PlayPoxy(Object target){
this.target = target;
}
//设置返回的代理对象方法
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
//具体处理增强功能的方法
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("Cglib代理模式 ~~ 开始");
Object returnVal = method.invoke(target, args);
System.out.println("Cglib代理模式 ~~ 提交");
return returnVal; //依赖函数的返回值也可以修改
}
}
public class Client {
public static void main(String[] args) {
PlayPoxy playPoxy = new PlayPoxy(new PlayImpl());
PlayImpl proxyInstance = (PlayImpl) playPoxy.getProxyInstance();
proxyInstance.play();
}
}
4.其他代理
防火墙代理:(内网穿透服务器对公网的访问)
缓存代理: 请求文件先到缓存取,如果没有就到数据库或公网取
远程代理: 本地的对象代理远程的对象像本地访问一样访问资源
同步代理: 代理需要多线程同步的对象(加上同步代码块)
1
5.模板(template method)模式
- 是什么?
1.是行为型模式
2.几个类的几个方法是一样的,部分不一样,有一个final方法写调用处理流程
3.缺点是每个不同实现需要子类实现,类爆炸
//抽象类写一个final方法以免被子类覆盖
//改进加入构子方法直接返回状态,如果模板方法判断是否加另外的东西,不用改模板,可以让子类覆盖达到灵活控制的效果
//覆盖,增加灵活性(实现其他功能)
public abstract class SoyMilk {
final void make(){
select();
if(customWantAdditions()==true){
add();
}
soap();
beat();
};
void select(){
System.out.println("挑选大豆");
};
abstract void add();
void soap(){
System.out.println("吸水");
};
void beat(){
System.out.println("打碎");
};
//构子增加拓展性
boolean customWantAdditions(){
return true;
}
}
//写他的子类
public class RedSoyMilk extends SoyMilk {
@Override
void add() {
System.out.println("添加红豆");
}
}
public class GreenSoyBean extends SoyMilk {
@Override
void add() {
System.out.println("加绿豆");
}
}
public class PureSoyMilk extends SoyMilk {
@Override
void add() {
}
@Override
boolean customWantAdditions(){
return false;
}
}
//测试
public class Client {
public static void main(String[] args) {
SoyMilk redSoyMilk = new RedSoyMilk();
redSoyMilk.make();
System.out.println("--------------");
SoyMilk greenSoyBean = new GreenSoyBean();
greenSoyBean.make();
System.out.println("制作纯豆奶");
SoyMilk pureSoyMilk = new PureSoyMilk();
pureSoyMilk.make();
}
}
//运行结果
挑选大豆
添加红豆
吸水
打碎
--------------
挑选大豆
加绿豆
吸水
打碎
制作纯豆奶
挑选大豆
吸水
打碎
16.模板方法在spring是应用
//抽象类定义模板方法的实现过程
//上面的类又有继承 ,到ClassPathXmlApplicationContext我们就可以直接使用了因为一层一层方法继承下来,所有功能完成了实现
文章来源:https://www.toymoban.com/news/detail-520462.html
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
String CONVERSION_SERVICE_BEAN_NAME = "conversionService";
String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver";
String ENVIRONMENT_BEAN_NAME = "environment";
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
void setId(String var1);
void setParent(ApplicationContext var1);
ConfigurableEnvironment getEnvironment();
void setEnvironment(ConfigurableEnvironment var1);
void addBeanFactoryPostProcessor(BeanFactoryPostProcessor var1);
void addApplicationListener(ApplicationListener<?> var1);
void refresh() throws BeansException, IllegalStateException;
void registerShutdownHook();
void close();
boolean isActive();
ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
}
//AbstractApplicationContext的refresh相当于make文章来源地址https://www.toymoban.com/news/detail-520462.html
public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean //继承和实现确定处理过程
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
//处理的过程 只是这里依赖外部依赖(组合进来)
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var5) {
this.destroyBeans();
this.cancelRefresh(var5);
throw var5;
}
}
}
//空实现
//onfreash是构子
protected void onRefresh() throws BeansException {
}
//GenericApplicationContext类覆盖了父类的方法(子类覆盖父类具体实现方法,但没有全部实现的流程)
protected final void refreshBeanFactory() throws IllegalStateException {
if (this.refreshed) {
throw new IllegalStateException("GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
} else {
this.beanFactory.setSerializationId(this.getId());
this.refreshed = true;
}
}
到了这里,关于3.设计模式之后七种模式桥接装饰者组合外观享元代理模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!