设计模式(三) ---- 七种结构性型设计模式
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了设计模式(三) ---- 七种结构性型设计模式,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6984字,纯文字阅读大概需要10分钟。
内容图文
七种结构性设计模式
1.适配器模式
目的:在java中的目的就是为了,让不兼容的类进行兼容。
分类:类适配器模式,对象适配器模式,接口适配器模式。
1.1类适配器
还是以这个插座的适配器我们来做分析,看一下这个例子:
对于220V的电压我们是不能直接使用的,因此我们需要通过一个适配器将他转换
使用适配器模式
原本的类:
package com.atguigu.adapter.classadapter; // 被适配的类 public class Voltage220V { // 输出220V的电压 public int output220V() { int src = 220; System.out.println("电压=" + src + "伏"); return src; } }
这是适配器类,实现类中只有一个output方法:
package com.atguigu.adapter.classadapter; // 适配器类 public class VoltageAdapter extends Voltage220V implements IVoltage5V { @Override publicint output5V() { // TODO Auto-generated method stub //获取到220V电压int srcV = output220V(); int dstV = srcV / 44 ; //转成 5vreturn dstV; } }
这就是类适配器的使用
1.2对象适配器
对于类适配器没有太多改变。
主要是没有去继承了,改用聚合
package com.atguigu.adapter.objectadapter; // 适配器类 public class VoltageAdapter implements IVoltage5V { private Voltage220V voltage220V; // 关联关系-聚合 看这一行
//通过构造器,传入一个 Voltage220V 实例public VoltageAdapter(Voltage220V voltage220v) { this.voltage220V = voltage220v; } @Override publicint output5V() { int dst = 0; if(null != voltage220V) { int src = voltage220V.output220V();//获取220V 电压 System.out.println("使用对象适配器,进行适配~~"); dst = src / 44; System.out.println("适配完成,输出的电压为=" + dst); } return dst; } }
1.3 接口适配器
这种模式看起来就比较霸气了,你不是要用吗?我就把你需要用到的所有方式全部准备好,你去选择一种就好
package com.atguigu.adapter.interfaceadapter; public interface Interface4 { public void output5v(); public void output10v(); public void output20v(); public void output220v(); }
然后再去调用。不想用的方法全部,空实现
1.4在SpringMVC中的使用
对应的页面请求,就来调用对应的控制器再去使用相应的适配器,就像相关的包装然后操作。
2 桥接模式
手机问题
这样会造成类爆炸的问题,而且很不容易扩展,于是我们引入了桥接模式
把功能和样式分开,看一眼主要代码。
package com.atguigu.bridge; // 接口 public interface Brand { void open(); void close(); void call(); }
package com.atguigu.bridge; public abstract class Phone { // 组合品牌 private Brand brand; // 构造器 public Phone(Brand brand) { super (); this.brand = brand; } protectedvoid open() { this.brand.open(); } protectedvoid close() { brand.close(); } protectedvoid call() { brand.call(); } }
这就是桥接模式,简单吧
桥接模式在JDBC中的使用
3装饰者模式
定制咖啡问题:根据客人订购的商品去定制类,会造成类爆炸问题
第一种方式
第二种方式
调料内置。
但是这样非常不适合项目的维护,改进难度大不符合ocp原则。
于是我们引入了装饰者模式
这是主要的喝咖啡类,一下的所有咖啡和配料都会继承
package com.atguigu.decorator; public abstract class Drink { public String des; // 描述privatefloat price = 0.0f; public String getDes() { return des; } publicvoid setDes(String des) { this.des = des; } publicfloat getPrice() { return price; } publicvoid setPrice(float price) { this.price = price; } //计算费用的抽象方法 //子类来实现publicabstractfloat cost(); }
这是咖啡类,具体的子类在构造器中初始化价格和描述就好了这里就不写了
package com.atguigu.decorator.coffce; import com.atguigu.decorator.Drink; public class Coffee extends Drink { @Override publicfloat cost() { // TODO Auto-generated method stubreturnsuper.getPrice(); } }
在原本咖啡的基础上拼接配料信息就可以了
package com.atguigu.decorator.Decorator; import com.atguigu.decorator.Drink; public class Decorator extends Drink { private Drink obj; public Decorator(Drink obj) { //??? // TODO Auto-generated constructor stubthis.obj = obj; } @Override publicfloat cost() { // TODO Auto-generated method stub // getPrice ??????returnsuper.getPrice() + obj.cost(); } @Override public String getDes() { // TODO Auto-generated method stub // obj.getDes() ??????????????return des + " " + getPrice() + " && " + obj.getDes(); } }
然后在主类中进行加载就可以了
Drink order = new LongBlack();
System.out.println("费用1=" + order.cost()); System.out.println("描述=" + order.getDes()); // 2. order 加入一份牛奶 order = new Milk(order); System.out.println("order 加入一份牛奶 费用 =" + order.cost()); System.out.println("order 加入一份牛奶 描述 = " + order.getDes());
这是运行结果
装饰者模式在JDK--io流中的使用
4组合模式
这是一个层级关系,组合模式就是把这种关系封装为树形结构,而不是继承关系
就是下图:
将下一层的类存储在集合之中
组合模式在JDK-- HashMap中的使用
5外观模式
影院为例:我们主类操作过多,不适合我们需要一个外观类来处理相应的操作
这样主类就可以只用调用外观就可以了
外观类进行分部就行拆解:主类对该类进行操作即可
外观模式在MyBatis中Configuration创建MetaObject的使用
6享元模式
针对对于可能会反复调用的组件,我们可以使用“池”的概念封装起来
比如:同一份广告对于不同网站的调用共用一份即可
用户类:
package com.atguigu.flyweight; public class User { private String name; public User(String name) { super (); this.name = name; } public String getName() { return name; } publicvoid setName(String name) { this.name = name; } }
网站类:
package com.atguigu.flyweight; // 具体网站 public class ConcreteWebSite extends WebSite { //共享的部分,内部状态private String type = ""; //网站发布的形式(类型) //构造器public ConcreteWebSite(String type) { this.type = type; } @Override publicvoid use(User user) { // TODO Auto-generated method stub System.out.println("网站的发布形式为:" + type + " 在使用中 .. 使用者是" + user.getName()); } }
创建类:
package com.atguigu.flyweight; import java.util.HashMap; // 网站工厂类,根据需要返回压一个网站 public class WebSiteFactory { // 集合, 充当池的作用 private 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); } //获取网站分类的总数 (池中有多少个网站类型)publicint getWebSiteCount() { return pool.size(); } }
在这个里面每次客户调用的就是同一个类。
在JDK--Integer中的使用
7 代理模式
一些功能的使用并不使用类直接使用,而是使用代理类来完成。
7.1静态代理
优点:在不修改目标对象的功能前提下进行扩展
缺点:代理类和目标对象实现相同的接口,所以很多代理类一旦接口的方法增加,目标对象和代理对象都要进行修改
7.2动态代理
public Object getProxyInstance() { // 说明 /* * public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定 //2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型 //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入 */ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub System.out.println("JDK代理开始~~"); //反射机制调用目标对象的方法 Object returnVal = method.invoke(target, args); System.out.println("JDK代理提交"); return returnVal; } }); }
主要依赖于早就写好了的Proxy代理类中的newProxyInstance 通过反射机制进行 动态代理
7.3Cglib代理
也叫子类代理,在没有接口的时候,就是用目标对象的子类进行代理。(ps:使用的时候需要导包)
package com.atguigu.proxy.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class ProxyFactory implements MethodInterceptor { //维护一个目标对象private Object target; //构造器,传入一个被代理的对象public ProxyFactory(Object target) { this.target = target; } //返回一个代理对象: 是 target 对象的代理对象public Object getProxyInstance() { //1. 创建一个工具类 Enhancer enhancer = new Enhancer(); //2. 设置父类 enhancer.setSuperclass(target.getClass()); //3. 设置回调函数 enhancer.setCallback(this); //4. 创建子类对象,即代理对象return enhancer.create(); } //重写 intercept 方法,会调用目标对象的方法 @Override public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub System.out.println("Cglib代理模式 ~~ 开始"); Object returnVal = method.invoke(target, args); System.out.println("Cglib代理模式 ~~ 提交"); return returnVal; } }
说实话对于这个代理我还没有怎么弄懂
在防火墙代理,缓存代理,远程代理和同步代理中有广泛应用
以上就是七种结构性设计模式。
原文:https://www.cnblogs.com/wdxjy/p/13877916.html
内容总结
以上是互联网集市为您收集整理的设计模式(三) ---- 七种结构性型设计模式全部内容,希望文章能够帮你解决设计模式(三) ---- 七种结构性型设计模式所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。