1.代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问
1.1简单实现静态代理
定义个购买的接口
public interface IShop {
void buy();
}
我这个人 需要购买
public class LiuWangShu implements IShop {
@Override
public void buy() {
System.out.println("购买");
}
}
这个人就是代理人 谁进来我就可以给他购买 像代购
public class Purchasing implements IShop {
private IShop mShop;
Purchasing(IShop shop) {
mShop = shop;
}
@Override
public void buy() {
mShop.buy();
}
}
我只要打个电话给代购 让他帮我买东西 它就帮我买了实现静态代理
public class Client {
Client() {
LiuWangShu liuWangShu = new LiuWangShu();
Purchasing purchasing = new Purchasing(liuWangShu);
purchasing.buy();
}
}
1.2 接下来我们看一下动态代理
实现InvocationHandler接口在动态 最终会执行invoke方法
public class DynamicPurchasing implements InvocationHandler {
private Object obj;
DynamicPurchasing(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(obj, args);
if (method.getName().equals("buy")) {
System.out.println("买买买");
}
return result;
}
}
在创建一个这个对象DynamicPurchasing 然后拿到liuWangShu这个类,最后在调用代理模式的newProxyInstance方法生产一个对象 然后调用对象方法
public class Client {
Client() {
LiuWangShu liuWangShu = new LiuWangShu();
Purchasing purchasing = new Purchasing(liuWangShu);
purchasing.buy();
DynamicPurchasing dynamicPurchasing = new DynamicPurchasing(liuWangShu);
ClassLoader classLoader = liuWangShu.getClass().getClassLoader();
IShop mIshop = (IShop) Proxy.newProxyInstance(classLoader, new Class[]{IShop.class}, dynamicPurchasing);
mIshop.buy();
}
}
1.3 优点解析
(1)主题类是实现业务逻辑,不用关心其他非本职工作
(2)主题类随时会发生改变,但因为它实现了公共的接口,所以代理类不做任何改变就可以使用
1.4 总结
代理模式分为静态代理和动态代理,静态代理说白了就调用你这个对象的已有方法,只不过通过应用传递给别人去调用了。动态代理其实就是通过java的动态代理机制去实现具体的方法,只是需要注意动态代理的各个参数和使用规则
2.装饰模式
定义:动态地给一个对象添加额外的职责,就增加功能来说,装饰模式比生成子类更加灵活
2.1 简单实现
这个是一个普通人
public abstract class Swordsman {
public abstract void attackMagic();
}
普通人一开始只有剑术
public class YangGuo extends Swordsman{
@Override
public void attackMagic() {
System.out.print("学习过剑术");
}
}
定义一个高手 谁传进来就教授武功
public abstract class Master extends Swordsman {
private Swordsman mSwordsman;
public Master(Swordsman mSwordsman) {
this.mSwordsman = mSwordsman;
}
public void attackMagic() {
mSwordsman.attackMagic();
}
}
洪七公是具体高手的实现 只有有人来就可以教授武功
public class HongQiGong extends Master {
public HongQiGong(Swordsman mSwordsman) {
super(mSwordsman);
}
@Override
public void attackMagic() {
super.attackMagic();
teachWuGong();
}
private void teachWuGong() {
Log.i("HongQiGong", "teachWuGong: 教授新武功");
}
}
洪七公实现了方法教授了武功
public class Client {
Client(){
YangGuo yangGuo = new YangGuo();
HongQiGong hongQiGong = new HongQiGong(yangGuo);
hongQiGong.attackMagic();
}
}
2.2使用场景
(1)在需要不影响对象定义情况下,以动态,透明的方式给单个对象添加职责。
(2)需要动态给对象增加功能,这些功能需要可以撤销的时候
2.3 优点
(1)通过装饰者,可以动态扩展一个对象的功能,在运行时候选择不同的装饰器,实现不同的行为
(2)有效避免了使用继承方式对对象功能带来的灵活性差,子类无限扩展问题。
(3)具体组件和具体装饰类可以独立变化,用户可以根据需要增加和新的组件类和装饰类,在使用的时候进行组合,原来代码可以不用改变
2.4 总结
装饰者就是先自己定义个类然后有个装饰类,将具体类传入装饰类中,在装饰类中做更多的处理操作,不同的装饰类可以有不同的操作
3.外观模式
定义:要求一个子系统的外部与内部的通信必须通过一个统一的对象进行。此模式提供一个统一高层模式,让子系统更加容易使用。
3.1 具体代码
定义一个招式系统
public class ZhaoShi {
public void TaiJiQuan(){
System.out.print("使用招式太极拳");
}
public void QiShangQuan(){
System.out.print("使用招式七伤拳");
}
public void ShenHuo(){
System.out.print("使用招式圣火令");
}
}
定义一个内功系统
public class NeiGong {
public void JiuYang(){
System.out.print("使用九阳神功");
}
public void QianKun(){
System.out.print("使用乾坤大挪移");
}
}
定义一个系统 这个系统会直接协调出招式的时候要怎么样调用其他武功系统,最后把结果处理好
public class ZhangWuJi {
private ZhaoShi zhaoShi;
private NeiGong neiGong;
public ZhangWuJi() {
zhaoShi = new ZhaoShi();
neiGong = new NeiGong();
}
public void QiShangQuan() {
neiGong.JiuYang();
zhaoShi.QiShangQuan();
}
}
客户端调用只需要说 我要哪个招式
public class Client {
public Client() {
ZhangWuJi zhangWuJi = new ZhangWuJi();
zhangWuJi.QiShangQuan();
}
}
3.2外观模式的使用场景和优缺点
(1)使用场景
构建一个有层次的子系统,使用外观欧式定义子系统每层,减少子系统之间相互依赖关系
外观模式提供一个简单的接口,对外隐藏子系统的具体实现并隔离变化,调用者非常简单,不需要知道内部子系统的实现细节
(2)优点
减少系统的相互依赖。所有的依赖都在外观类
对用户隐藏了子系统的实现,减少用户对子系统的偶合,就算子系统变化了,用户也不会感知到
加强了安全性,子系统不在如果不在外观类中开通,就无法访问到子系统的方法。
(3)缺点
如果子系统发生改变,那么可能要修改外观类
3.3总结
其实外观模式就是一个类它会协调很多子系统,然后对外提供一个很简单的方法给用户去使用,用户不需要知道外观类具体是怎么协调子系统之间进行工作的,比如很多开源框架就是这样子干的。
4 享元模式
定义使用共享对象有效支持大量细粒度的对象
4.1代码实现
先定义个实体类
public class Goods implements IGoods {
private String name;
private String version;
Goods(String name) {
this.name = name;
}
@Override
public void showGoodsPrice(String version) {
if (version.equals("32G")) {
System.out.print("价格为5199");
} else {
System.out.print("价格为5999");
}
}
}
定义一个享元工厂
public class GoodsFactory {
private static Map<String, Goods> pool = new HashMap<String, Goods>();
public static Goods getGoods(String name) {
if (pool.containsKey(name)) {
System.out.print("使用缓存 key为" + name);
return pool.get(name);
} else {
Goods goods = new Goods(name);
pool.put(name, goods);
System.out.print("创建商品,key为" + name);
return goods;
}
}
}
最后使用享元模式
public class Client {
Client(){
Goods iphone7 = GoodsFactory.getGoods("iphone7");
iphone7.showGoodsPrice("32");
Goods iphone8 = GoodsFactory.getGoods("iphone7");
iphone8.showGoodsPrice("32");
}
}
会发现只有第一次创建了 其他时候都是使用缓存的对象
4.2 使用场景及优缺点
系统中存在大量相似的对象
需要缓存池的场景
4.3 总结
其实所谓享元模式就是存在一个map 将对象存储进去,没有的话就创建一个存储进去,如果有的话直接返回回去。