github交流
意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
@Setter
@Getter
public class ExPressCompany {
double price; //价格
int speed; //快递发送速度
int piece; //件数
@Override
public String toString() {
return "ExPressCompany{" +
"price=" + price +
", speed=" + speed +
", piece=" + piece +
'}';
}
}
public class ShunFengExpressCompany extends ExPressCompany{
public ShunFengExpressCompany(double price, int speed,int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
}
public class YuanTongExpressCompany extends ExPressCompany {
public YuanTongExpressCompany(double price, int speed, int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
}
需求1
根据用户选择的快递计算好 支付的快递费,快递需要消耗的时间,如果是顺丰,快递发送速度默认是1,如果是圆通快递,快递发送速度默认是2 。
public class StrategyTest1 {
public static void main(String[] args) {
ExPressCompany exPressCompany = create(2, 4);
System.err.println(exPressCompany);
}
/**
* @param companyType 1 = 顺丰, 2 = 圆通
* @param piece 件数
*/
public static ExPressCompany create(int companyType, int piece) {
ExPressCompany exPressCompany = new ExPressCompany();
if (companyType <= 0 || piece <= 0) return exPressCompany;
if (1 == companyType) exPressCompany = new ShunFengExpressCompany(15, 1,piece);
else if (2 == companyType) exPressCompany = new YuanTongExpressCompany(10, 2,piece);
//如果是顺丰,并且件数大于3 ,那么 价格打八折
if (1 == companyType && piece > 3) exPressCompany.setPrice(exPressCompany.getPrice() * piece * 0.8);
//如果是圆通,并且件数大于5 ,那么 价格打五折
else if (2 == companyType && piece > 5) exPressCompany.setPrice(exPressCompany.getPrice() * piece * 0.5);
//后续可能还有很多业务逻辑,更多的if else
return exPressCompany;
}
}
//定义快递公司 生成对象策略
public interface ExpressCompanyStrategy {
ExPressCompany create(int piece);
}
//顺丰快递公司 对象生成策略
public class ShunFengExpressCompanyStrategyImpl implements ExpressCompanyStrategy{
@Override
public ExPressCompany create(int piece) {
ExPressCompany exPressCompany = new ShunFengExpressCompany(15, 1,piece);
if (piece > 3) exPressCompany.setPrice(exPressCompany.getPrice() * piece * 0.8);
return exPressCompany;
}
}
//圆通快递公司 对象生成策略
public class YuanTongExpressCompanyStrategyImpl implements ExpressCompanyStrategy {
@Override
public ExPressCompany create(int piece) {
ExPressCompany exPressCompany = new YuanTongExpressCompany(10, 2,piece);
if (piece > 5) exPressCompany.setPrice(exPressCompany.getPrice() * piece * 0.5);
return exPressCompany;
}
}
public class StrategyTest1 {
private static final Map<Integer,ExpressCompanyStrategy> EXPRESS_COMPANY_STRATEGY_MAP = new HashMap<>();
static {
EXPRESS_COMPANY_STRATEGY_MAP.put(1, new ShunFengExpressCompanyStrategyImpl());
EXPRESS_COMPANY_STRATEGY_MAP.put(2, new YuanTongExpressCompanyStrategyImpl());
}
public static void main(String[] args) {
final int companyType = 1;
//策略模式版本
ExPressCompany shunfStrategy = create2(EXPRESS_COMPANY_STRATEGY_MAP.get(companyType), 4);
System.err.println(shunfStrategy);
}
public static ExPressCompany create2(ExpressCompanyStrategy expressCompanyStrategy, int piece) {
return expressCompanyStrategy.create(piece);
}
}
基础代码:
public interface MyComparator {
int sort (Object o);
}
@Setter
@Getter
public abstract class BaseExPressCompany implements MyComparator {
double price; //价格
int speed; //快递发送速度
int piece; //件数
@Override
public String toString() {
return "ExPressCompany{" +
"price=" + price +
", speed=" + speed +
", piece=" + piece +
'}';
}
}
public class ShunFengExpressCompanyBaseExPressCompany extends BaseExPressCompany {
public ShunFengExpressCompanyBaseExPressCompany(double price, int speed, int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
@Override
public int sort(Object o) {
ShunFengExpressCompanyBaseExPressCompany shunFengExpressCompany = (ShunFengExpressCompanyBaseExPressCompany) o;
if (this.speed < shunFengExpressCompany.speed) return 1;
else if (this.speed > shunFengExpressCompany.speed) return -1;
return 0;
}
}
public class YuanTongExpressCompanyBaseExPressCompany extends BaseExPressCompany {
public YuanTongExpressCompanyBaseExPressCompany(double price, int speed, int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
@Override
public int sort(Object o) {
//TODO
return 0;
}
}
public interface ExpressCompanyStrategy {
BaseExPressCompany create(ExpressDelegate delegate);
}
@Setter
@Getter
public class ExpressDelegate {
int piece ;
int price ;
int speed;
public ExpressDelegate(int piece, int speed) {
this.piece = piece;
this.speed = speed;
}
public ExpressDelegate() {
}
}
public class ShunFengExpressCompanyStrategyImpl implements ExpressCompanyStrategy {
@Override
public BaseExPressCompany create(ExpressDelegate delegate) {
BaseExPressCompany exPressCompany = new ShunFengExpressCompanyBaseExPressCompany(15, delegate.speed,delegate.piece);
if (delegate.piece > 3) exPressCompany.setPrice(exPressCompany.getPrice() * delegate.piece * 0.8);
return exPressCompany;
}
}
public class YuanTongExpressCompanyStrategyImpl implements ExpressCompanyStrategy {
@Override
public BaseExPressCompany create(ExpressDelegate delegate) {
BaseExPressCompany exPressCompany = new YuanTongExpressCompanyBaseExPressCompany(10, delegate.speed, delegate.piece);
if (delegate.piece > 5) exPressCompany.setPrice(exPressCompany.getPrice() * delegate.piece * 0.5);
return exPressCompany;
}
}
public class StrategyTest2 {
private static final Map<Integer, ExpressCompanyStrategy> EXPRESS_COMPANY_STRATEGY_MAP = new HashMap<>();
static {
EXPRESS_COMPANY_STRATEGY_MAP.put(1, new ShunFengExpressCompanyStrategyImpl());
EXPRESS_COMPANY_STRATEGY_MAP.put(2, new YuanTongExpressCompanyStrategyImpl());
}
public static void main(String[] args) {
final int companyType = 1;
ExpressCompanyStrategy expressCompanyStrategy = EXPRESS_COMPANY_STRATEGY_MAP.get(companyType);
List<BaseExPressCompany> companyList = generator(expressCompanyStrategy, 2,5, 1, 6);
System.out.println(companyList);
List<BaseExPressCompany> soft = softBySpeed(companyList);
System.out.println("============");
System.err.println(soft);
}
/**
* @description: 生成数据
* @param expressCompanyStrategy
* @param piece
* @date: 6/26/2020 7:17 PM
*/
public static List<BaseExPressCompany> generator(ExpressCompanyStrategy expressCompanyStrategy, int... piece) {
List<BaseExPressCompany> result = new ArrayList<>(piece.length);
ExpressDelegate delegate = null;
List<Integer> speedList = new ArrayList<>();
speedList.add(2);
speedList.add(1);
speedList.add(5);
speedList.add(3);
for (int value : piece) {
int speedTmp = 0;
if (!speedList.isEmpty()) speedTmp = speedList.get(0);
delegate = new ExpressDelegate(value, speedTmp);
result.add(expressCompanyStrategy.create(delegate));
speedList.remove(0);
}
return result;
}
/**
* @description: 根据发送速度排序
* @param companyList
* @date: 6/26/2020 7:17 PM
*/
public static List<BaseExPressCompany> sortBySpeed(List<BaseExPressCompany> companyList) {
List<BaseExPressCompany> result = new ArrayList<>(companyList.size());
BaseExPressCompany[] array = companyList.toArray(new BaseExPressCompany[companyList.size()]);
for (int i = 0; i < array.length; i++) {
for (int j = i; j < array.length; j++) {
if (array[j].sort(array[i]) >= 1){
swap(array,i,j);
}
}
}
result = Arrays.asList(array);
return result;
}
/**
* @description: 将数组中的i下标数据与j下标数据进行交换
* @param arr
* @param i
* @param j
* @date: 6/26/2020 7:16 PM
*/
public static void swap (BaseExPressCompany [] arr ,int i ,int j){
BaseExPressCompany tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
不过这样还存在两个缺点
MyComparator
接口,但是入参是Object.每次sort的时候需要强转一下(强迫症需要优化这里),其实只需要在结合泛型就行啦。这样就不用强转了,看的也赏心悦目//修改MyComparator如下
public interface MyComparator<T> {
int sort (T t);
}
//对应的BaseExPressCompany 和BaseExPressCompany 的实现类也需要处理一下
@Setter
@Getter
public abstract class BaseExPressCompany implements MyComparator<BaseExPressCompany> {
double price; //价格
int speed; //快递发送速度
int piece; //件数
@Override
public String toString() {
return "ExPressCompany{" +
"price=" + price +
", speed=" + speed +
", piece=" + piece +
'}';
}
}
//有了泛型就不需要强转了
public class ShunFengExpressCompanyBaseExPressCompany extends BaseExPressCompany {
public ShunFengExpressCompanyBaseExPressCompany(double price, int speed, int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
@Override
public int sort(BaseExPressCompany baseExPressCompany) {
if (this.speed < baseExPressCompany.speed) return 1;
else if (this.speed > baseExPressCompany.speed) return -1;
return 0;
}
}
//对 MyComparator 再次进行改造
public interface MyComparator<T> {
int sort (T t1,T t2);
}
public class ShunFengExpressCompanyBaseExPressCompany extends BaseExPressCompany {
public ShunFengExpressCompanyBaseExPressCompany(double price, int speed, int piece) {
this.price = price;
this.speed = speed;
this.piece = piece;
}
public ShunFengExpressCompanyBaseExPressCompany() {
}
@Override
public int sort(BaseExPressCompany t1, BaseExPressCompany t2) {
if (t1.speed < t2.speed) return 1;
else if (t1.speed > t2.speed) return -1;
return 0;
}
}
//以及修改 sortBySpeed,方法
//再调用sortBySpeed(此时这个方法其实不仅仅针对Speed属性排序了)方法的时候,需要传入一个MyComparator比较器对象,具体的实现sort()方法由子类去实现(方法入参指定一个对象,这样我们可以结合lambda 进行排序处理)
public static List<BaseExPressCompany> sortBySpeed(List<BaseExPressCompany> companyList,MyComparator<BaseExPressCompany> comparator) {
List<BaseExPressCompany> result = new ArrayList<>(companyList.size());
BaseExPressCompany[] array = companyList.toArray(new BaseExPressCompany[companyList.size()]);
for (int i = 0; i < array.length; i++) {
for (int j = i; j < array.length; j++) {
if (comparator.sort(array[j],array[i])>= 1){
swap(array,i,j);
}
}
}
result = Arrays.asList(array);
return result;
}
//使用lambda进行排序
public static void main(String[] args) {
final int companyType = 1;
ExpressCompanyStrategy expressCompanyStrategy = EXPRESS_COMPANY_STRATEGY_MAP.get(companyType);
List<BaseExPressCompany> companyList = generator(expressCompanyStrategy, 2,5, 1, 6);
List<BaseExPressCompany> soft = sortBySpeed(companyList,(t1,t2)->{
if (t1.getPrice() < t2.getPrice()) return 1;
else if (t1.getPrice() > t2.getPrice()) return -1;
return 0;
});
System.err.println(soft);
}
后续还有根据泛型的处理,内容大同小异。源码已分享github