问题:根据电表显示的用电量计算用户的电费,注意:电表用不同的电表,电费有不同的计算方法
解析:运用访问者模式。访问这模式结构:1、抽象访问者(一般用接口来实现);2、具体访问者(实现接口的类);3、抽象元素(一般用抽象类实现);4、具体元素(继承抽象类的类)。在本问题中,电表用抽象类抽象出来,计费方法看成是计表员接口,而用不同的计费方法来实现这个计表员访问者接口。
package face;//访问者模式:核心是双重分派
interface Visitor{ //抽象访问者,一般用接口来实现
public double visit(AmmeterElement element);
}
abstract class AmmeterElement{ //抽象元素,一般用抽象类来实现
public abstract void accept(Visitor visitor);
public abstract double showElectricAmount();
public abstract void setElectricAmount(double n);
}
/*具体访问者,实现Visitor接口的类,本问题有两个具体访问者,分别是HomeAmmerterVisitor类(模拟负责家用电计费的计表员)
和IndustryAmmeteVisitor类(模拟负责工业用电计费的计表员)*/
class HomeAmmerterVisitor implements Visitor{ //家用电计费的计表员
@Override
public double visit(AmmeterElement element) {
double charge = 0;
double unitOne = 0.6,unitTwo = 1.05;
int basic = 6000;
double n = element.showElectricAmount();
if( n <= basic){
charge = n*unitOne;
}else{
charge = basic*unitOne + (n-basic)*unitTwo;
}
return charge;
}
}
class IndustryAmmeteVisitor implements Visitor{ //工业用电计费的计表员
@Override
public double visit(AmmeterElement element) {
double charge = 0;
double unitOne = 1.25,unitTwo = 2.78;
int basic = 15000;
double n = element.showElectricAmount();
if( n <= basic){
charge = n*unitOne;
}else{
charge = basic*unitOne + (n-basic)*unitTwo;
}
return charge;
}
}
class Ammeter extends AmmeterElement{ //具体被访问者访问的具体元素
double electricAmount;
@Override
public void accept(Visitor visitor) {
double feiyong = visitor.visit(this); //让访问者访问当前元素
System.out.println("当前电表的用户需要交纳的电费:"+feiyong+"元");
}
@Override
public double showElectricAmount() {
return electricAmount;
}
@Override
public void setElectricAmount(double n) {
electricAmount = n;
}
}
public class Demo05 {
public static void main(String[] args) {
AmmeterElement 电表 = new Ammeter(); //向上转型,把一个AmmeterElement类用其子类来实例化(方便具体元素的扩展)
电表.setElectricAmount(5678);
Visitor 计表员 = new HomeAmmerterVisitor(); //按照家用电标准计费的“计表员”
电表.accept(计表员);
计表员 = new IndustryAmmeteVisitor(); //按照工业用电标准计费的“计表员”
电表.accept(计表员);
}
}
核心技术:双重分派,在访问者模式中,被访者(即抽象类的元素角色)首先调用accept方法接收访问者,被接收的访问者再调用visit(Element element)访问当前对象