在项目中,我们经常会遇见一个功能需要采用多种算法或策略的情况,此时,我们写一个类来实现多种算法或策略以及在一个方法中通过if/else语句来实现多种算法或策略,这些方法称为硬编码(实际上我就这么干过 - -)。这样做违反了单一职能原则和开闭原则,会导致之后的代码很难维护。
策略模式的应用场景:
1.针对同一类型的问题的多种处理方式,仅仅是具体行为有差别
2.需要安全的封装多种同一类型操作时
3.同一抽象类有多个子类,需要使用if/else来进行选择
当一个问题有多个解决方案时,简单地采用if/else或switch/case这种简单方案进行选择,会使得代码耦合性高,代码臃肿,逻辑复杂,难以维护。一旦需要处理大量的逻辑封装,规则的较大变更以及增加新的解决方案就会对代码进行较大程度地修改。策略模式通过构建抽象,将不同的策略构建为一个具体实现,通过不同的策略实现算法替换,使得逻辑更为直观也更具可扩展性。
策略模式的优点:
1.结构清晰,使用简单直观
2.耦合度较低,扩展方便
3.操作封装彻底,数据更为安全
策略模式的缺点:
随着策略增加,子类会繁多
其实策略模式的应用在现实生活中无处不在,比如:当我们需要结账的时候,就有多种策略可以选择,支付宝,微信,信用卡这些都可以看作策略类,调用其相应的接口实现支付,而不需要知道这些策略类的内部如何实现支付功能。
在实际项目中经常出现的变更之一就是数据存储的变更,比如从dbf文件,isf文件,数据库等。
public interface dataStorePolicy
{
bool addRow(Row row);
bool deleteRow(int key);
int getCount();
Row getRow(int key);
}
public class dbfStore implements dataStorePolicy
{
@Override
bool addRow(Row row)
{
system.out.println("dbf添加记录");
return true;
}
@Override
bool deleteRow(int key)
{
system.out.println("dbf删除特定记录");
return true;
}
@Override
int getCount()
{
system.out.println("dbf返回记录数");
return 0;
}
@Override
Row getRow(int key)
{
system.out.println("dbf获取特定记录");
return NULL;
}
}
public class sqlStore implements sqlStorePolicy
{
@Override
bool addRow(Row row)
{
system.out.println("sql添加记录");
return true;
}
@Override
bool deleteRow(int key)
{
system.out.println("sql删除特定记录");
return true;
}
@Override
int getCount()
{
system.out.println("sql返回记录数");
return 0;
}
@Override
Row getRow(int key)
{
system.out.println("sql获取特定记录");
return NULL;
}
}
public class Context
{
private dataStorePolicy policy;
context(dataStorePolicy dataPolicy)
{
policy = dataPolicy;
}
public void setPolicy(dataStorePolicy dataPolicy)
{
policy = dataPolicy;
}
bool addRow(Row row)
{
return policy.addRow(row);
}
bool deleteRow(Row row)
{
return policy.deleteRow(row);
}
int getCount()
{
return policy.getCount();
}
Row getRow(int key)
{
return policy.getRow(key);
}
}
public class client
{
dataStorePolicy dataPolicy = new dbfStore();
Context context(dataPolicy);
context.getCount();
context.getRow(1);
dataStorePolicy data2Policy = new sqlStore();
context.setPolicy(data2Policy);
context.getCount();
context.getRow(1);
}