适配器模式
定义:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作。
适配器模式又叫变压器模式,也叫做包装模式。
适配器模式的三个角色:
1. target:目标角色。定义把其他类转换为何种接口,也就是我们的期望接口。
2. Adaptee:原角色。你想把谁转换成目标角色,这个谁就是原角色。它是已经存在的、运行良好的类或对象。经过适配器角色的包装,它会成为一个崭新的角色。
3. Adapter:适配器角色。通过继承或类关联的方式,把原角色转换成目标角色。
通用源码:
public interface Target {
//目标角色有自己的方法
public void request();
}
public class ConcreteTarget implements Target {
public void request() {
System.out.println("I have nothing to do. if you need any help,pls call me!"); }
}
public class Adaptee{
//原有的业务逻辑
public void doSomething(){
System.out.println("I'm kind of busy,leave me alone,pls!");
}
}
public class Adapter extends Adaptee implements Target {
public void request() {
super.doSomething();
}
}
public class Client {
public static void main(String[] args) {
//原有的业务逻辑
Target target = new ConcreteTarget();
target.request();
//增加了适配器角色之后的业务逻辑
Target target2 = new Adapter();
target2.request();
}
}
- 优点:可以让两个没有任何关系的类在一起运行。增加了类的透明性。提高了类的服用度。灵活性非常好。如果某一天不想哟适配器了,删除掉这个适配器就可以了,其他的代码不用修改。
- 使用场景:你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的选择。比如系统扩展了,需要使用一个已有或新建立的类,但这个类又不符合系统的接口,便可以使用适配器模式。
- 注意事项:适配器模式不是为了解决还在开发阶段的问题,而是解决正在服役的项目问题。主要使用场景是扩展应用。而且项目一定要遵守依赖倒置原则和里氏替换原则,否则即使在适合使用适配器的场景下,也会带来非常大的改造。
适配器模式的扩展:
对象适配器。
与上面的类适配器的区别是:类适配器是类间继承,对象适配器是对象的合成关系。也可以说是类的关联关系。对象适配器是通过类间的关联关系进行耦合的,因此比较灵活,比如修补原角色的隐形缺陷,关联其他对象等。而类适配器只能通过复写原角色的方法进行扩展。实际项目中对象适配器用得比较多。
迭代器模式
定义:它提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
注:目前是一个没落的模式,基本没人会单独写一个迭代器,除非是产品性质的开发。
角色:
1. Iterator抽象迭代器:负责定义访问和遍历元素的接口。而且基本上是有固定的3个方法。first()获得第一个元素,next()访问下一个元素,isDone()是否已经访问到底部。
2. ConcreteIterator具体迭代器:实现迭代器接口,完成容器元素的遍历。
3. Aggregate抽象容器:提供创建具体迭代器角色的接口,必然提供一个类似createIterator这样的方法。
4. ConcreteAggregate具体容器:创建出容纳迭代器对象。
通用源码:
public interface Iterator{
public Object next();
public boolean hasNext();
public boolean remove();
}
public class ConcreteIterator implements Iterator{
private Vector vector = new Vector();
public int crusor = 0;
public ConcreteIterator(Vector _vector){
this.vector = _vector;
}
public boolean hasNext(){
if(this.crusor == this.vector.size()){
return false;
}else{
return true;
}
}
public Object next(){
Object result = null;
if(this.hasNext()){
result = this.vector.get(this.cursor++);
}else{
result = null;
}
return result;
}
public boolean remove(){
this.vector.remove(this.cursor);
return true;
}
}
public interface Aggregate(){
public void add(Object object);
public void remove(Object object);
public Iterator iterator();
}
public class ConcreteAggregate implements Aggregate{
private Vecotr vector = new Vector();
public void add(Object object){
this.vector.add(object);
}
public void remove(Object object){
this.vector.remove(object);
}
public Iterator iterator(){
return new ConcreteIterator(this.vector);
}
}
public class Client {
public static void main(String[] args) {
Aggregate agg = new ConcreteAggregate();
agg.add("abc");
agg.add("aaa");
agg.add("1234");
Iterator iterator = agg.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
java已经把迭代器写好了。因为有很多容器类。也不用我们再去写迭代器模式了。
组合模式
将对象组合成树形结构以表示“部分–整体”的层次结构,使得用户对单个和组合对象的使用具有一致性。
角色:
1. Component抽象构件角色:定义组合对象的共有方法和属性,可以定义一些 默认的行为或属性。
2. Leaf叶子构件:其下再也没有其他的分支。也就是遍历的最小单位。
3. Composite树枝构件:组合树枝节点和叶子节点形成一个树形结构。
通用源码:
public abstract class Component {
//个体和公体都具有的共享
public void doSomething(){
}
}
public class Composite extends Component {
//构件容器
private ArrayList<Component> componentArrayList = new ArrayList<Component>();
//增加一个叶子构件或树枝构件
public void add(Component component){
this.componentArrayList.add(component);
}
public void remove(Component component){
this.componentArrayList.remove(component);
}
//获得分支下所有的叶子构件和分支构件
public ArrayList<Component> getChildren(){
return this.componentArrayList;
}
}
public class Leaf extends Component {
/*
* //可以覆写父类方法
* public void doSomething(){
*
* }
*/
}
public class Client {
public static void main(String[] args) {
Composite root = new Composite();
root.doSomething();
Composite branch = new Composite();
Leaf leaf = new Leaf();
root.add(branch);
branch.add(leaf);
}
public static void display(Composite root){
for(Component c:root.getChildren()){
if(c instanceof Leaf){
c.doSomething();
}else{
display((Composite)c);
}
}
}
}
优点:
1. 高层模块调用简单。一棵树形结构的所有节点都是Component。局部和整体对调用者来说没有任何区别。高层模块不必关系自己处理的是单个对象还是整个组合结构。
2. 节点自由增加。想增加一个节点只要找到他的父节点就成。非常容易扩展。
缺点:在场景类中的定义中,使用树枝和树叶时直接用了实现类,与依赖倒置原则冲突。
使用场景:
1. 维护和展示部分–整体关系的场景,如树形菜单,文件和文件夹管理等。
2. 从一个整体能够独立出部分模块或功能的场景。