- 组合模式(Composite Pattern)
定义:组合模式让你可以优化处理递归或分级数据结构,通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口表示,使得客户对单个对象和组合对象的使用具有一致性(例如文件夹和文件,父菜单和子菜单)
应用场景:希望客户端可以忽略组合对象与单个对象的差异,对象层次具备整体和部分,呈树形结构
通用实现方式:定义一个抽象组件类(或接口,决定于实现类中行为的差异性),包含树枝和叶子的共有属性和方法,这些方法对外开放,有基础实现,叶子类和树枝类均继承自该组件,树枝节点中定义一个可以容纳抽象组件类型的容器,各自重写共有方法,以至于两种对象对于客户端来说访问接口是相同的
优点:简化客户端调用,因为客户端的调用接口对两种子类型的调用接口是一致的,新增组件类型时符合开闭原则,方便对整个层次进行控制
缺点:设计更加抽象,想要实现差异性较大的组件时,并不适用
JDK中组合模式的实现--HashMap,内部类node对象
简单实现:
package com.CompositePattern;
/**
* @author yangxiaozhen
* 手写HashMap简单实现
* @date 2022/5/15-13:03
*/
public class MyHashMap implements MyMap {
private int CAPACITY = 1000;
//数组
Node[] nodes = new Node[CAPACITY];
//内部类节点
static class Node {
int key, value;
Node next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
private int getIndex(int key) {
int hashCode = Integer.hashCode(key);
hashCode ^= (hashCode >>> 16);
return hashCode % CAPACITY;
}
public void put(int key, int value) {
int index = getIndex(key);
Node target = nodes[index], tmp = target;
//对应下标的node不为空,则发生了hash碰撞,采用链地址方式解决碰撞问题
if (tmp != null) {
//遍历链表直到node.next为空则表示到达末尾,把末尾node赋给tmp
Node prev = null;
while (tmp != null) {
//遍历链表如果当前key的值已存在于链表中则覆盖掉value,并返回
if (tmp.key == key) {
tmp.value = value;
return;
}
//用prev存储最后一个节点
prev = tmp;
tmp = tmp.next;
}
//把找到的最后一个节点引用,给到高作用域的tmp变量
tmp = prev;
}
Node node = new Node(key, value);
if (tmp != null) {
//把新建的node放到末尾
tmp.next = node;
} else {//当前index下的node为空,则直接赋值新建的node
nodes[index] = node;
}
}
public int get(int key) {
int index = getIndex(key);
Node target = nodes[index];
if (target == null) {
return 0;
}
while (target != null) {
if (target.key == key) {
return target.value;
}
target = target.next;
}
return 0;
}
public void remove(int key) {
int index = getIndex(key);
Node now = nodes[index];
if (now != null) {
Node prev = null;
while (now != null) {
if (now.key == key) {
if (prev != null) {
prev.next = now.next;
} else {
nodes[index] = now.next;
}
now.next = null;
return;
}
prev = now;
now = now.next;
}
}
}
public static void main(String[] args) {
String s ="001";
System.out.println(s.hashCode());
System.out.println(s.hashCode()>>>1);
System.out.println(s.hashCode()^s.hashCode()>>>1);
}
}
- 适配器模式(Adapter Pattern)
定义:又叫变压器模式,致力于将一个类的接口编程客户端所期望的另一种接口,从而使得原本因为接口不一致导致无法一起工作的两个类能够一期工作
在软件开发中,基本上任何问题都能通过增加一个中间层来解决,适配器模式就相当于时这种中间层,将一个接口转化为另外一种符合需求的接口
例如我们原先有一个‘轮子’能生成220v的电(生产电需要从煤->发电站总之非常复杂),但是我们的客户端接口已经定义需要输入5v的电,这时候我们就可以通过建造一个‘适配器’,将我们原先生产220v电的接口,转化成输出5v电的接口,这样我们便可以复用原先轮子的复杂过程代码。
应用场景:已经存在的类,他的方法和需求不匹配,适配器模式不应该在软件设计阶段使用,而是随着软件维护,由于不同产品造成的功能类似而接口不相同情况下的解决方案,像是亡羊补牢的解决方案
细化形式:类适配器,对象适配器,接口适配器
包含角色:目标角色,源角色,适配器
对象适配器:通过组合来实现适配器功能,适配器类实现目标接口,并持有源实例
类适配器:继承源角色,实现目标接口,在实现方法的时候调用父类方法来达到复用
接口适配器:适用场景是,源目标接口方法过多,有一些可能是现在不需要的,那么则通过抽象类去实现源接口,并给所以抽象方法以默认实现,这样客户端就不用去关注不需要的方法,只需要重写需要的方法即可
优点:提高类的复用,符合开闭原则
缺点:增加代码阅读难度
JDK和主流框架中的应用:目前对于适配器模式的理解还不深刻,后面再感受感受再补充进来
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)