多态,是java三大面向对象的特性之一,其他还有封装和继承,有时人们也会将抽象算进去,称为四大特性。在日常写代码时,我们基本每天都在看到使用到多态,那么,什么是多态呢,又该怎么正确使用呢,这就是今天要去研究的了。。
1.什么是多态:
其实提到多态就不得不提到继承,因为要实现多态,首先第一点必须要有继承一个父类,然后重写或实现其中的方法,最后用最简单的一句话就是:父类型的引用指向子类型的对象。用一句比较通俗的话:同一操作作用于不同的对象,可以产生不同的效果。这就是多态。
2.多态的作用:
使用多态可以解决项目中紧偶合的问题,提高程序的可扩展性.是OOP原则的一个具体的实现,应用程序不必为每一个子类编写功能调用,只需要对父类进行处理即可。大大提高程序的可复用性。子类的功能也可以被基类的方法或引用变量所调用,向后兼容,可以提高可扩充性和可维护性。
介绍完了多态,也是回顾一下java基础的特性,在23种设计模式中,也有一种设计模式借鉴的多态的思想,“策略模式”。
设计模式是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样(取自百度百科)那么23种设计模式中的策略模式又是什么样的呢?
策略模式的思想:
策略模式的思想是针对一组算法,将每一种算法都封装到具有共同接口的独立的类中,从而是它们可以相互替换。策略模式的最大特点是使得算法可以在不影响客户端的情况下发生变化,从而改变不同的功能。策略模式体现了面向对象程序设计中非常重要的两个原则:
封装变化的概念。
编程中使用接口,而不是使用的是具体的实现类(面向接口编程)。
实现策略模式需要的三个基础角色:
上下文角色(Context):用来操作策略的上下文环境,屏蔽高层模块(客户端)对策略,算法的直接访问,封装可能存在的变化。
抽象策略角色(Strategy):规定策略或算法的行为。
具体策略角色(ConcreteStrategy):具体的策略或算法实现。
举个例子:
假设现在有两个数与一个运算符,要求使用该运算符操作这两个数。不使用策略模式的话,我们可以通过判断运算符符号,对这两个数进行运算。
public class Calculator {
public int calc(int a, int b, final String symbol) {
int result = 0;
if ("+".equals(symbol)) {
result = a + b;
} else if ("-".equals(symbol)) {
result = a - b;
}
return result;
}
}
但是这样写的话,如果我们现在要扩展乘法*或除法/运算,那么就要在calc方法内增加对应的if…else判断,代码臃肿并且扩展性太低。
而如果采用策略模式,将各种运算符的计算都归并到对应具体策略,这样,就能简化代码并且带来很好的扩展性,具体代码如下:
public class Client {
public static void main(String[] args) {
ICalculator calculator = new Add();
Context context = new Context(calculator);
int result = context.calc(1,2);
System.out.println(result);
}
public interface ICalculator {
int calc(int a, int b);
}
public static class Add implements ICalculator {
@Override
public int calc(int a, int b) {
return a + b;
}
}
public static class Sub implements ICalculator {
@Override
public int calc(int a, int b) {
return a - b;
}
}
public static class Multi implements ICalculator {
@Override
public int calc(int a, int b) {
return a * b;
}
}
public static class Divide implements ICalculator {
@Override
public int calc(int a, int b) {
return a / b;
}
}
public static class Context {
private ICalculator mCalculator;
public Context(ICalculator calculator) {
this.mCalculator = calculator;
}
public public int calc(int a, int b) {
return this.mCalculator.calc(a, b);
}
}
}
从上面代码中,我们可以看到,我们完全消除了对运算符号进行判断的哪些if…else的冗余代码,取而代之的是用户直接决定使用哪种算法,然后交由上下文获取结果。并且上面代码中我们还扩展了乘法Multi和除法Divide运算,所需要做的就只是扩展相应的策略类而已。
但是每一种设计模式的优点虽然是明显的,可也是会有一些缺点的,所以我们要了解这些缺点,在实际场景中,尽量的避免缺点的产生。
策略模式的优缺点:
优点:
1.消除了if…else冗余代码的使用,让代码更加干净。
2.易于扩展,当我们需要不同的逻辑时只需要添加相应的策略类即可。
3.易于维护,针对不同的功能,我们只需要维护相对应的策略类即可。
4.职责清晰,策略模式只针对同一类型问题进行解决。
缺点:
1.客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
2.由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么对象的数目就会很可观。