不屈的码农Java架构师系列Java

GoF之适配器模式、策略模式详解

2019-10-10  本文已影响0人  Java架构师CAT

适配器模式(Adapter Pattern)

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

优点

1、可以让任何两个没有关联的类一起运行。

2、提高了类的复用。

3、增加了类的透明度。

4、灵活性和扩展性都非常好,符合“开闭原则”。

缺点:

1、过多地使用适配器,会让系统变复杂。比如,明明看到调用的是A 接口,其实内部被适配成了 B 接口的实现。如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。

2.由于 JAVA至多继承一个类,所以至多只能适配一个适配者类,而且目标类必须是抽象类。

使用场景:有动机地修改一个正常运行的系统的接口,这时应该考虑使用适配器模式。

注意事项:适配器不是在详细设计时添加的,而是解决正在服役的项目的问题。

类适配器模式(adapter pattern)

具体实现:通过电源适配器,将电源输入220V(适配者)转换为5V输出(目标)。

//目标角色

public interface PowerTarget{

    public int output5V();

}

//适配者角色

public class PowerAdaptee{

    private int output =  220;

    public int output220V() {

        System.out.println("电源输出电压:" + output);

        return output;

    }

}

//适配器角色

public class PowerAdapterextends PowerAdapteeimplements PowerTarget{

    @Override

    public int output5V() {

        int output =output220V();

        System.out.println("电源适配器开始工作,此时输出电压是:" + output);

        output = 5;

        System.out.println("电源适配器工作完成,此时输出电压是:" + output);

        return output;

    }

}

电源适配器类实现了电源目标,继承了适配者。

//类适配器模式测试

public class ClassAdapterPatternTest{

    public static void main(String[] args) {

        PowerTargettarget = new PowerAdapter();

        target.output5V();

    }

}

对象适配器模式(object adapter pattern)

对象适配器模式在运行时实现target(目标)接口。在这种适配器模式中,适配器包装了一个类实例。适配器通过调用包装对象实例的方法实现适配。

代码示例和类适配器模式只有Adapter类有不同,其他都一样,只贴上Adapter类。

//适配器角色

public class PowerAdapterimplements PowerTarget{

    private PowerAdaptee powerAdaptee;

    public PowerAdapter(PowerAdapteepowerAdaptee) {

        super();

        this.powerAdaptee = powerAdaptee;

    }

    @Override

    public int output5V() {

        int output = powerAdaptee.output220V();

        System.out.println("电源适配器开始工作,此时输出电压是:" + output);

        output = 5;

        System.out.println("电源适配器工作完成,此时输出电压是:" + output);

        return output;

    }

}

实现了PowerTarget(目标角色),在创建对象时引入PowerAdaptee(适配者角色)。

缺省适配器模式(defaultadapter pattern)(客户端,继承b,调用b中的方法,不必直接实现a(直接实现a需要实现a中的所有的方法))

当不需要全部实现接口提供的方法时,可以设计一个适配器抽象类实现接口,并为接口中的每个方法提供默认方法,抽象类的子类就可以有选择的覆盖父类的某些方法实现需求,它适用于一个接口不想使用所有的方法的情况。

在java8后,接口中可以有default方法,就不需要这种缺省适配器模式了。接口中方法都设置为default,实现为空,这样同样同样可以达到缺省适配器模式同样的效果。

策略模式(Strategy Pattern)也叫 政策模式(Policy Pattern)。

指的是对象具备某个行为,但是在不同的场景中,该行为有不同的实现算法。比如一个人的交税比率与他的工资有关,不同的工资水平对应不同的税率。

优点:

1、算法可以自由切换。

2、避免使用多重条件判断。

3、扩展性良好。

缺点:

1、策略类会增多。

2、所有策略类都需要对外暴露。

具体实现:建立加减乘算法族,解决在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

//创建一个接口,定策略或算法的行为。

public interface Strategy{

    public int doOperation(int num1, int num2);

}

//创建实现接口的实体类,里面包含具体的策略或算法实现。利用多态,使行为在不同场景下产生不同结果。

public class OperationAddimplements Strategy{

    @Override

    public int doOperation(int num1, int num2) {

        return num1 + num2;

    }

}

public class OperationSubstractimplements Strategy{

    @Override

    public int doOperation(int num1, int num2) {

        return num1 - num2;

    }

}

public class OperationMultiplyimplements Strategy{

    @Override

    public int doOperation(int num1, int num2) {

        return num1 * num2;

    }

}

//创建Context类,用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化;

public class Context {

    private Strategy strategy;

    public Context(){

    }

    public SetStrategy(Strategy strategy){

        this.strategy = strategy;

    }

    public int executeStrategy(int num1, int num2){

        return strategy.doOperation(num1, num2);

    }

}

//使用 Context 来查看当它改变策略 Strategy 时的行为变化。

public class StrategyPatternClient{

    public static void main(String[] args) {

        Contextcontext = new Context();

        context.SetStrategy(new OperationAdd());

        System.out.println("10 + 5 =" + context.executeStrategy(10, 5));

        context.SetStrategy(new OperationSubstract());

        System.out.println("10 - 5 =" + context.executeStrategy(10, 5));

        context.SetStrategy(new OperationMultiply());

        System.out.println("10 * 5 =" + context.executeStrategy(10, 5));

    }

}

输出结果:

      10 + 5 = 15

    10 - 5 = 5

      10 * 5 =50

注意事项:如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

原文:https://mp.weixin.qq.com/s/g20WQyzJNmvkH-kLPZRYBA

作者:专注一行代码

来源:微信公众号

上一篇 下一篇

猜你喜欢

热点阅读