我们经常需要比较两个对象,或者形成一个行为策略,而究竟采用哪一种策略呢?是把策略写死在函数里?如果我们商城打折,那每次都得修改这个函数?或许我们可以把策略抽取程一个类,用面向对象来解决,后文加上了用配置文件来修改这种策略,使得其更加灵活(用到反射)
comparator
如果我们要实现某两个类的比较机制,可以实现comparable接口,实现里面的compareTo()方法,那么我们就可以实现二者比较了
package com.ylf.compare; public interface Comparable { public int compareTo(Object o); } |
假设我们这里的比较类是Computer
package com.ylf.compare; import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction; public class Computer implements Comparable{ private int price; private int ability; public Computer(int price, int ability) { super(); this.price = price; this.ability = ability; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public int getAbility() { return ability; } public void setAbility(int ability) { this.ability = ability; } @Override public int compareTo(Object o) { if(!(o instanceof Computer)) return -2; Computer c = (Computer)o; if(this.price < c.getPrice()) return -1; else if(this.price == c.getPrice()) return 0; else return 1; } } |
那么我们在Main里面比较很简单,只需要简单调用CompareTo方法就可以了
package com.ylf.compare; public class Main { public static void main(String[] args) { Computer c1 = new Computer(4000, 90); Computer c2 = new Computer(5000, 95); int re = c1.compareTo(c2); System.out.println("result:"+re); } } |
但是问题来了,如果我们要比较的不是价格,而是电脑性能了怎么办呢?
很简单,改下compareTo()方法就可以了,但是这样还是很麻烦,如果我们希望在一个配置文件里实现比较策略,那么这样就不行了,从面向对象角度出发,比较的物体是对象,比较这个过程或者说比较这个策略我们是否也可以看成一个对象?
假设我们有Comparator这个比较策略,在compareTo()方法里调用这个比较策略来实现返回比较结果,如果我们比较价格,那就创建一个PriceComparator 如果 比较性能,那就创建 AbilityComparator 这样虽然在类数目上增加了,但是我们类的灵活度大大提高了。
也就是让我们的电脑实体拥有一个比较器(comarator)这个比较器专门用来比较,至于怎么比较那就是比较器实现问题!这里用组合形式降低了类之间的耦合度
形容的在恰当点,二者要发生关系,如果太死板,没啥花样,每次都一样,容易厌倦,如果把二者发生的这个关系抽象出一个类,那么每次玩啥花样呢?不用想,直接去买一个中介,每次都很不一样啦!
首先添加一个比较器,这里作为抽象类
package com.ylf.compare; public abstract class Comparator { public abstract int compare(Object o1, Object o2); } |
computer类里改变就是添加了一个比较器的持有,同时比较方法采用比较器进行
package com.ylf.compare; import javax.swing.text.html.HTMLDocument.HTMLReader.IsindexAction; public class Computer implements Comparable{ private int price; private int ability; private Comparator comparator; public Computer(int price, int ability) { super(); this.price = price; this.ability = ability; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public int getAbility() { return ability; } public void setAbility(int ability) { this.ability = ability; } public Comparator getComparator() { return comparator; } public void setComparator(Comparator comparator) { this.comparator = comparator; } @Override public int compareTo(Object o) { //这里把具体比较策略转交给比较器 return comparator.compare(this, o); } } |
假设我们这里实现了性能比较器
package com.ylf.compare; public class AbilityComparator extends Comparator{ @Override public int compare(Object o1, Object o2) { if(!(o1 instanceof Computer) || !(o2 instanceof Computer)) return -2; Computer c1 = (Computer)o1; Computer c2 = (Computer)o2; if(c1.getAbility() < c2.getAbility()) return -1; else if(c1.getAbility() == c2.getAbility()) return 0; else return 1; } } |
那么Main里比较就只要借助Computer对象里的比较器进行就可以
package com.ylf.compare; public class Main { public static void main(String[] args) { Computer c1 = new Computer(4000, 95); Computer c2 = new Computer(5000, 95); Comparator c = new PriceComparator(); c1.setComparator(c); int re = c1.compareTo(c2); System.out.println("result:"+re); } } |
如果我们有一个配置文件,记录了比较器的选择,那么修改他就好了,然后在Main 方法里
package com.ylf.compare; public class Main { public static void main(String[] args) { Computer c1 = new Computer(4000, 95); Computer c2 = new Computer(5000, 95); //Comparator c = new PriceComparator(); try{ //假设我们从配置文件读取了配置信息在comparatorStr String comparatorStr = "com.ylf.compare.PriceComparator"; //反射生成Class Class comparatorClass = Class.forName(comparatorStr); Comparator c = (Comparator)comparatorClass.newInstance(); c1.setComparator(c); int re = c1.compareTo(c2); System.out.println("result:"+re); }catch(Exception e){ e.printStackTrace(); } } } |