共计 8059 个字符,预计需要花费 21 分钟才能阅读完成。
适配器模式
所谓适配器模式,就是把一个类的构造转换成另外一个类的接口。使得本来因为接口不兼容而不能工作的类都可能一起工作。
在生活中比拟常见的就是当咱们想连贯显示器的时候,vga 须要转成 hdmi,还有电源适配,比方可能须要 220v 的充电头,然而只有 110v 的充电头,那么就须要将 220v 的充电头适配成 110v 的充电头。
Adaptee:
须要适配的就代码,旧接口
Adapter:
将调用转发给Adaptee
的适配器类
Target:
反对的新接口
适配器模式 UML
类适配器模式
Target
public interface Target {void output110v();
}
Adaptee
public class Adaptee {public void output220v() {System.out.println("输入电压");
}
}
Adapter
public class Adapter extends Adaptee implements Target {
@Override
public void output110v() {this.output220v();
}
}
这里须要留神的是 Adapter
是 继承了源类而实现了指标类
Client
public class Client {public static void main(String[] args) {Target target = new Adapter();
target.output110v();}
}
尽管咱们是应用了 output110v
的充电头,然而通过 Adapter 后,最终通过 this.output220v()
会调用output220v
的充电头,这就是把 output220v
适配成了output110v
。
对象适配器模式
其实说得这么高大上,其实就是Adaptor
的实现形式不同,类适配器模式采纳继承了源类(也就是须要适配的类)实现了指标类。
这样就存在一个问题,当咱们须要适配多个类的时候就会呈现问题,因为 java 中是容许 实现多个接口,然而只能继承一个类。
为了解决这个问题,咱们能够把须要适配的类作为Adapter
的成员变量,而后通过构造函数进行适配
public class NewAdapter implements Target{
Adaptee adaptee;
public NewAdapter(Adaptee adaptee) {this.adaptee = adaptee;}
@Override
public void output110v() {adaptee.output220v();
}
}
代理模式
代理模式也算是比拟罕用的设计模式之一,大家接触最多的 spring aop,就是采纳动静代理模式来实现的。代理模式能够分为一般代理模式,强制代理模式,动静代理模式,也是本文着重解说的,当然还有其代理模式。
先来用一段代码来领会代理模式,场景是玩家打游戏。
Subject:
独特接口,客户端应用的现有接口
RealSubject:
实在对象的类
ProxySubject:
代理对象类
代理模式 UML
一般代理模式
通过下面的例子,置信对大家都对代理模式有点感觉了,然而如同又不那么失当,下面的测试类种,还是须要新建一个 player,这就相当于什么,相当于咱们是在手机上登录了游戏,而后再把手机给代练者代练。而事实上,常常是把账号密码给代练即可。
这就引出了一般代理模式,客户端不能拜访实在角色,只能拜访代理角色,咱们可能晓得代理的存在。
Subject
public interface SubjectNormalGamePlayer {public void login();
public void upgrade();
public void matches();}
RealSubject
public class RealSubjectNormalPlayerImpl implements SubjectNormalGamePlayer {
private String name;
private String password;
public RealSubjectNormalPlayerImpl(String name, String password) {
this.name = name;
this.password = password;
}
@Override
public void login() {if(name.equals("cutey") && password.equals("123456")) {System.out.println(name + "登录胜利");
}
}
@Override
public void upgrade() {System.out.println(name + "降级");
}
@Override
public void matches() {System.out.println(name + "打排位赛");
}
}
ProxySubject
public class ProxySubjectNormalPlayerImpl implements SubjectNormalGamePlayer {
SubjectNormalGamePlayer gamePlayer;
// 留神这里的区别,咱们是拿账号和明码去登录实在角色
// 并不是间接拿实在角色的手机来打
public ProxySubjectNormalPlayerImpl(String name, String password) {gamePlayer = new RealSubjectNormalPlayerImpl(name, password);
}
@Override
public void login() {System.out.print("代练:");
gamePlayer.login();}
@Override
public void upgrade() {System.out.print("代练:");
gamePlayer.upgrade();}
@Override
public void matches() {System.out.print("代练:");
gamePlayer.matches();}
}
Client
public class Client {public static void main(String[] args) {
// 通过测试类也很显著区别,不必要显示结构实在角色类
SubjectNormalGamePlayer proxy = new ProxySubjectNormalPlayerImpl("cutey", "123456");
proxy.login();
proxy.upgrade();
proxy.matches();}
}
强制代理
一般代理呢是去找到一个代理对象帮打,然而强制代理呢,次要是体现在“强制”,角色类会指定一个代理,其它形式找来的代理不能帮我打,肯定要用我指定的代理才行。
Subject
和一般代理模式大部分代码一样,不同的是加了一个 强制指定代理对象。
public interface SubjectForceGamePlayer {
// 省略登录、降级和打排位等办法
// 强制指定代理对象
public SubjectForceGamePlayer getForceProxy();}
RealSubject
public class ForceGamePlayerImpl implements IForceGamePlayer {
private String name;
private String password;
private IForceGamePlayer proxy = null; // 指定须要谁来代理
public ForceGamePlayerImpl(String name, String password) {
this.name = name;
this.password = password;
}
@Override
public IForceGamePlayer getForceProxy() {
// 强制指定代理类,并且只有这样能力给 proxy 赋值
proxy = new ForceProxyGamePlayerImpl(this);
return proxy;
}
@Override
public void login() {
// 只有不是本人指定的 proxy,其它形式 proxy 必定是 null
if(proxy != null) {if(name.equals("imperfect") && password.equals("123456")) {System.out.println(name + "登录胜利");
}
} else {System.out.println("须要代理");
}
}
@Override
public void upgrade() {if(proxy != null) {System.out.println(name + "降级");
} else {System.out.println("须要代理");
}
}
@Override
public void matches() {if(proxy != null) {System.out.println(name + "打排位赛");
} else {System.out.println("须要代理");
}
}
}
ProxySubject
public class ProxySubjectForcePlayerImpl implements SubjectForceGamePlayer {
private SubjectForceGamePlayer gamePlayer;
// 接管被代理对象的指定
public ProxySubjectForcePlayerImpl(SubjectForceGamePlayer gamePlayer) {this.gamePlayer = gamePlayer;}
// 省略登录、降级和打较量的办法
// 没有代理对象,临时返回本人
@Override
public SubjectForceGamePlayer getForceProxy() {return this;}
}
Client
public class Client {public static void main(String[] args) {wrongProxy1();
wrongProxy2();
correctProxy();}
public static void correctProxy() {SubjectForceGamePlayer player = new RealSubjectForcePlayerImpl("cutey", "123456");
// 你这个代理必须是我指定的,并且强制要有
SubjectForceGamePlayer proxy = player.getForceProxy();
proxy.login();
proxy.upgrade();
proxy.matches();}
public static void wrongProxy1() {SubjectForceGamePlayer player = new RealSubjectForcePlayerImpl("cutey", "123456");
SubjectForceGamePlayer proxy = new ProxySubjectForcePlayerImpl(player);
proxy.login();
proxy.upgrade();
proxy.matches();}
public static void wrongProxy2() {SubjectForceGamePlayer player = new RealSubjectForcePlayerImpl("cutey", "123456");
player.login();
player.upgrade();
player.matches();}
}
动静代理
这个应该是代理模式中用的比拟多的,也是我感觉最须要各位小伙伴了解并且把握的。所谓动静代理是指,不必在编译器指定为谁代理,而是在运行期再取得被代理的对象并且执行代理的办法。
上面将要讲的例子是利用 jdk 中提供的 InvocationHandler 和 Proxy 类
Subject
、RealSubject
都和一般代理模式一样
ProxySubject
咱们不晓得要给谁代理,所以要用到的是继承 InvocationHandler 类
public class ProxySubjectDynamicPlayerImpl implements InvocationHandler {
Class cls = null; // 要代理的类
Object obj = null; // 须要代理的对象
// 指定须要代理的对象
public ProxySubjectDynamicPlayerImpl(Object obj) {this.obj = obj;}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 调用代理对象的办法
Object result = method.invoke(this.obj, args);
if(method.getName().equalsIgnoreCase("login")) {System.out.println("异地登陆揭示:有人登录我的账户");
}
return result;
}
}
Client
public class Client {public static void main(String[] args) {SubjectDynamicPlayer player = new RealSubjectDynamicPlayerImpl("imperfect", "123456");
// 把须要代理的信息交给 handler,还记得 invoke 办法吗
// 在 invoke 办法中曾经实现了被代理对象的办法
InvocationHandler handler = new ProxySubjectDynamicPlayerImpl(player);
// 获取被代理类的类加载属性
ClassLoader cl = player.getClass().getClassLoader();
// 获取被代理类的接口
Class[] interfaces = player.getClass().getInterfaces();
// 把上述的三个信息交给 Proxy 创立出一个代理类
SubjectDynamicPlayer proxy = (SubjectDynamicPlayer) Proxy.newProxyInstance(cl, interfaces, handler);
proxy.login();
proxy.upgrade();
proxy.matches();}
}
在编译时咱们是齐全不晓得给谁代理,一切都是在运行时才晓得,这就是“动静”
装璜模式
装璜模式就是动静地给一个对象增加一些恩爱的职责,就减少性能来说,装璜模式比生成子类更为灵便。
无论干什么,最重要的都是取长补短,对于卖手机也是如此,必定是把卖点具体地介绍,而对于毛病能不提就不提。
Component:
定义一个对象的接口,能够给这些对象动静地增加职责
ConcreteComponent:
具体的对象
Decorator:
装璜抽象类,继承了 Component,从外类来扩大 Component
ConcentrateDecorator:
具体的装璜类
装璜模式 UML
装璜模式
Component
public abstract class ComponentMobile {
// 产品名字
private String name;
// 省略 get,set,tostring 办法
public abstract void showDetails();
public abstract void onSale(String userName);
}
Concentrate Component
public class ConcreteComponentOnePlus extends ComponentMobile {public ConcreteComponentOnePlus(String name) {super(name);
}
@Override
public void showDetails() {System.out.println("处理器:骁龙 888 \r\n 拍照:哈苏业余模式 \r\n 屏幕:2k+120hz 柔性屏 \r\n 充电:65w 快充");
}
@Override
public void onSale(String userName) {System.out.println(userName + "购买了" + getName());
}
}
Decorator
public abstract class Decorator extends ComponentMobile {
// 把要装璜的手机拿给我
private ComponentMobile mobile;
public Decorator(String name, ComponentMobile mobile) {super(name);
this.mobile = mobile;
}
// 细节还是要展现的
// 只不过怎么展现呢,子类能够加以润饰
public void showDetails() {mobile.showDetails();
}
// 手机也是要发售的
public void onSale(String name) {mobile.onSale(name);
}
}
留神,咱们手机的细节还是要展现的,不能说做的不好就不说进去,坑骗消费者。能把你认出来叫化妆,不能把你认出来叫整容,咱们讲的是装璜模式,不是整容模式。
Concrete Decorator
public class ConcreteDecoratorSystem extends Decorator {public ConcreteDecoratorSystem(String name, ComponentMobile mobile) {super(name, mobile);
}
// 装璜零碎
public void decorateScreen() {System.out.println("出厂装备了 ColorOS,其它型号的手机也会逐渐适配");
}
@Override
public void showDetails() {
// 想先介绍了零碎,再说其余参数
decorateScreen();
super.showDetails();}
}
public class ConcreteDecoratorPrice extends Decorator {public ConcreteDecoratorPrice(String name, ComponentMobile mobile) {super(name, mobile);
}
// 颁布价格
public void decoratePrice() {System.out.println("8 + 128:4999");
System.out.println("8 + 256: 5499");
}
@Override
public void showDetails() {super.showDetails();
// 介绍完其它的后,颁布性价比较高的价格
decoratePrice();}
}
Client
public class Client {public static void main(String[] args) {
// 手机发布会,原产品
ComponentMobile mobile = new ConcreteComponentOnePlus("OnePlus 9 Pro");
// 装璜下零碎
mobile = new ConcreteDecoratorSystem(mobile.getName(), mobile);
// 装璜下价格
mobile = new ConcreteDecoratorPrice(mobile.getName(), mobile);
mobile.showDetails();
// 用户一看,诶,不错不错,买了
mobile.onSale("cutey");
}
}