(→Compiling and Running) |
|||
(3 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{TOCright}} | {{TOCright}} | ||
− | = | + | = Problema = |
− | Uma agência de cobrança de impostos tornou-se famosa por permitir adaptar métodos de cobrança de impostos de forma muito flexível. Os contribuintes (Taxpayer) são pessoas (Person), empresas (Company) e regiões (Region). As pessoas trabalham nas empresas e as empresas estão sediadas em regiões. Todos têm rendimentos (as pessoas e as regiões a partir das empresas e as empresas a partir de pessoas, regiões e outras empresas) e todos devem pagar os seus impostos. | + | Uma agência de cobrança de impostos tornou-se famosa por permitir adaptar métodos de cobrança de impostos de forma muito flexível. Os contribuintes ('''Taxpayer''') são pessoas ('''Person'''), empresas ('''Company''') e regiões ('''Region'''). As pessoas trabalham nas empresas e as empresas estão sediadas em regiões. Todos têm rendimentos (as pessoas e as regiões a partir das empresas e as empresas a partir de pessoas, regiões e outras empresas) e todos devem pagar os seus impostos. |
− | O sucesso da agência advém da facilidade com que cria variações do seu produto, o premiado FriendlyIRS. Estas aplicações permitem interrogar cada contribuinte de forma adaptada, tanto ao contribuinte, como à situação de cobrança desejada. | + | O sucesso da agência advém da facilidade com que cria variações do seu produto, o premiado '''FriendlyIRS'''. Estas aplicações permitem interrogar cada contribuinte de forma adaptada, tanto ao contribuinte, como à situação de cobrança desejada. |
− | Assim, além da cobrança em habitual, através do seu produto VanillaTaxes, permite ainda cobrar menos impostos se o rendimento for menor que um dado valor ou se a população (número de contribuintes numa empresa ou numa região) for inferior a um dado valor de referência. Para isso, disponibiliza o seu produto BecauseWeCare. | + | Assim, além da cobrança em habitual, através do seu produto '''VanillaTaxes''', permite ainda cobrar menos impostos se o rendimento for menor que um dado valor ou se a população (número de contribuintes numa empresa ou numa região) for inferior a um dado valor de referência. Para isso, disponibiliza o seu produto '''BecauseWeCare'''. |
− | * A versão implementada por VanillaTaxes funciona por cobrança acumulada. Cada pessoa paga uma unidade monetária e cada empresa paga o equivalente à soma das contribuições individuais dos seus empregados. Cada região paga o equivalente à soma das contribuições das empresas nela sediadas. | + | * A versão implementada por '''VanillaTaxes''' funciona por cobrança acumulada. Cada pessoa paga uma unidade monetária e cada empresa paga o equivalente à soma das contribuições individuais dos seus empregados. Cada região paga o equivalente à soma das contribuições das empresas nela sediadas. |
− | * A versão implementada por BecauseWeCare é como a anterior, mas considera ainda se o rendimento apurado é inferior a limiares de referência (BecauseWeCare.LOW, para o rendimento mínimo, mas apenas para pessoas e empresas; e BecauseWeCare.POP, para a população mínima, apenas para regiões), aplicando desconto de 10% se se verificar algum limiar. | + | * A versão implementada por '''BecauseWeCare''' é como a anterior, mas considera ainda se o rendimento apurado é inferior a limiares de referência ('''BecauseWeCare.LOW''', para o rendimento mínimo, mas apenas para pessoas e empresas; e '''BecauseWeCare.POP''', para a população mínima, apenas para regiões), aplicando desconto de 10% se se verificar algum limiar. |
Implemente todas as classes mencionadas: | Implemente todas as classes mencionadas: | ||
− | * Implemente esquematicamente as classes Taxpayer, Person, Company e Region, i.e., considere apenas as características estritamente necessárias para resolução do problema. As relações estruturais entre as classes devem ser explicitadas (atributos), mas não é necessário explicitar relações funcionais (métodos, interacção, etc.). | + | * Implemente esquematicamente as classes '''Taxpayer''', '''Person''', '''Company''' e '''Region''', i.e., considere apenas as características estritamente necessárias para resolução do problema. As relações estruturais entre as classes devem ser explicitadas (atributos), mas não é necessário explicitar relações funcionais (métodos, interacção, etc.). |
− | * Implemente completamente as classes FriendlyIRS, VanillaTaxes e BecauseWeCare. | + | * Implemente completamente as classes '''FriendlyIRS''', '''VanillaTaxes''' e '''BecauseWeCare'''. |
Crie um exemplo (main) que ilustre a aplicação das diferentes classes. | Crie um exemplo (main) que ilustre a aplicação das diferentes classes. | ||
− | = | + | = Solução = |
== Taxpayer Classes == | == Taxpayer Classes == | ||
{{CollapsedCode|Ficheiro '''Taxpayer.java'''| | {{CollapsedCode|Ficheiro '''Taxpayer.java'''| | ||
− | < | + | <source lang="java"> |
/** | /** | ||
* Basic taxpayer. | * Basic taxpayer. | ||
*/ | */ | ||
public abstract class Taxpayer { | public abstract class Taxpayer { | ||
− | + | /** | |
− | + | * No actual value is returned in this case. | |
− | + | * | |
− | + | * @param irs | |
− | + | * the visitor used to compute the revenue. | |
− | + | * @return tax payed by this taxpayer. | |
− | + | */ | |
− | + | public double accept(FriendlyIRS irs) { | |
− | + | throw new UnsupportedOperationException(); | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
{{CollapsedCode|Ficheiro '''Person.java'''| | {{CollapsedCode|Ficheiro '''Person.java'''| | ||
− | < | + | <source lang="java"> |
/** | /** | ||
* Individual taxpayer. | * Individual taxpayer. | ||
− | * | + | * |
* We omitted the initialisation code. | * We omitted the initialisation code. | ||
*/ | */ | ||
public class Person extends Taxpayer { | public class Person extends Taxpayer { | ||
− | + | /** | |
− | + | * @see Taxpayer#accept(FriendlyIRS) | |
− | + | */ | |
− | + | @Override | |
− | + | public double accept(FriendlyIRS irs) { | |
− | + | return irs.taxPerson(this); | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
{{CollapsedCode|Ficheiro '''Company.java'''| | {{CollapsedCode|Ficheiro '''Company.java'''| | ||
− | < | + | <source lang="java"> |
import java.util.ArrayList; | import java.util.ArrayList; | ||
/** | /** | ||
* A company has employees (persons). | * A company has employees (persons). | ||
− | * | + | * |
* We omitted the initialisation code. | * We omitted the initialisation code. | ||
*/ | */ | ||
public class Company extends Taxpayer { | public class Company extends Taxpayer { | ||
− | + | /** | |
− | + | * The employees in this company. | |
− | + | */ | |
− | + | private ArrayList<Person> _employees = new ArrayList<Person>(); | |
− | + | /** | |
− | + | * Simple constructor for initialising the company with some employees. | |
− | + | */ | |
− | + | public Company() { | |
− | + | int count = (int) (Math.random() * 100); | |
− | + | for (int i = 0; i < count; i++) | |
− | + | _employees.add(new Person()); | |
− | + | } | |
− | + | /** | |
− | + | * @return size of company (number of employees). | |
− | + | */ | |
− | + | public int size() { | |
− | + | return _employees.size(); | |
− | + | } | |
− | + | /** | |
− | + | * @param index | |
− | + | * @return an employee | |
− | + | */ | |
− | + | public Person getEmployee(int index) { | |
− | + | return _employees.get(index); | |
− | + | } | |
− | + | /** | |
− | + | * @see Taxpayer#accept(FriendlyIRS) | |
− | + | */ | |
− | + | @Override | |
− | + | public double accept(FriendlyIRS irs) { | |
− | + | return irs.taxCompany(this); | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
{{CollapsedCode|Ficheiro '''Region.java'''| | {{CollapsedCode|Ficheiro '''Region.java'''| | ||
− | < | + | <source lang="java"> |
import java.util.ArrayList; | import java.util.ArrayList; | ||
/** | /** | ||
* A region has companies. | * A region has companies. | ||
− | * | + | * |
* We omitted the initialisation code. | * We omitted the initialisation code. | ||
*/ | */ | ||
public class Region extends Taxpayer { | public class Region extends Taxpayer { | ||
− | + | /** | |
− | + | * The companies in this region. | |
− | + | */ | |
− | + | private ArrayList<Company> _companies = new ArrayList<Company>(); | |
− | + | /** | |
− | + | * Simple constructor for initialising the region with some companies. | |
− | + | */ | |
− | + | public Region() { | |
− | + | int count = (int) (Math.random() * 100); | |
− | + | for (int i = 0; i < count; i++) | |
− | + | _companies.add(new Company()); | |
− | + | } | |
− | + | /** | |
− | + | * @return size of region (number of companies). | |
− | + | */ | |
− | + | public int size() { | |
− | + | return _companies.size(); | |
− | + | } | |
− | + | /** | |
− | + | * @param index | |
− | + | * @return a company | |
− | + | */ | |
− | + | public Company getCompany(int index) { | |
− | + | return _companies.get(index); | |
− | + | } | |
− | + | /** | |
− | + | * @see Taxpayer#accept(FriendlyIRS) | |
− | + | */ | |
− | + | @Override | |
− | + | public double accept(FriendlyIRS irs) { | |
− | + | return irs.taxRegion(this); | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
Line 166: | Line 166: | ||
{{CollapsedCode|Ficheiro '''FriendlyIRS.java'''| | {{CollapsedCode|Ficheiro '''FriendlyIRS.java'''| | ||
− | < | + | <source lang="java"> |
/** | /** | ||
* The IRS computing visitor interface. | * The IRS computing visitor interface. | ||
*/ | */ | ||
public abstract class FriendlyIRS { | public abstract class FriendlyIRS { | ||
− | + | /** | |
− | + | * @param person | |
− | + | * @return tax payed by this person. | |
− | + | */ | |
− | + | public abstract double taxPerson(Person person); | |
− | + | /** | |
− | + | * @param company | |
− | + | * @return tax payed by this company. | |
− | + | */ | |
− | + | public abstract double taxCompany(Company company); | |
− | + | /** | |
− | + | * @param region | |
− | + | * @return tax payed by this region. | |
− | + | */ | |
− | + | public abstract double taxRegion(Region region); | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
Line 195: | Line 195: | ||
{{CollapsedCode|Ficheiro '''VanillaTaxes.java'''| | {{CollapsedCode|Ficheiro '''VanillaTaxes.java'''| | ||
− | < | + | <source lang="java"> |
/** | /** | ||
* Usual tax calculator. | * Usual tax calculator. | ||
Line 201: | Line 201: | ||
public class VanillaTaxes extends FriendlyIRS { | public class VanillaTaxes extends FriendlyIRS { | ||
− | + | /** | |
− | + | * @see FriendlyIRS#taxCompany(Company) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxCompany(Company company) { | |
− | + | double tax = 0; | |
− | + | for (int index = 0; index < company.size(); index++) | |
− | + | tax += company.getEmployee(index).accept(this); | |
− | + | return tax; | |
− | + | } | |
− | + | /** | |
− | + | * @see FriendlyIRS#taxPerson(Person) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxPerson(Person person) { | |
− | + | return 1; | |
− | + | } | |
− | + | /** | |
− | + | * @see FriendlyIRS#taxRegion(Region) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxRegion(Region region) { | |
− | + | double tax = 0; | |
− | + | for (int index = 0; index < region.size(); index++) | |
− | + | tax += region.getCompany(index).accept(this); | |
− | + | return tax; | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
Line 238: | Line 238: | ||
{{CollapsedCode|Ficheiro '''BecauseWeCare.java'''| | {{CollapsedCode|Ficheiro '''BecauseWeCare.java'''| | ||
− | < | + | <source lang="java"> |
/** | /** | ||
* The discount tax system. | * The discount tax system. | ||
Line 244: | Line 244: | ||
public class BecauseWeCare extends FriendlyIRS { | public class BecauseWeCare extends FriendlyIRS { | ||
− | + | /** | |
− | + | * Low water marker for revenue. | |
− | + | */ | |
− | + | private final int LOW = 1; | |
− | + | /** | |
− | + | * Low water marker for population. | |
− | + | */ | |
− | + | private final int POP = 50; | |
− | + | /** | |
− | + | * @see FriendlyIRS#taxCompany(Company) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxCompany(Company company) { | |
− | + | double tax = 0; | |
− | + | for (int index = 0; index < company.size(); index++) | |
− | + | tax += company.getEmployee(index).accept(this); | |
− | + | if (company.size() < POP || tax < LOW) | |
− | + | tax *= .9; | |
− | + | return tax; | |
− | + | } | |
− | + | /** | |
− | + | * In this case, we chose not to test the LOW level (simply because we know | |
− | + | * the value is the same). | |
− | + | * | |
− | + | * @see FriendlyIRS#taxPerson(Person) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxPerson(Person person) { | |
− | + | return 1; | |
− | + | } | |
− | + | /** | |
− | + | * @see FriendlyIRS#taxRegion(Region) | |
− | + | */ | |
− | + | @Override | |
− | + | public double taxRegion(Region region) { | |
− | + | double tax = 0; | |
− | + | for (int index = 0; index < region.size(); index++) | |
− | + | tax += region.getCompany(index).accept(this); | |
− | + | if (region.size() < POP || tax < LOW) | |
− | + | tax *= .9; | |
− | + | return tax; | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
Line 300: | Line 300: | ||
{{CollapsedCode|Ficheiro '''App.java'''| | {{CollapsedCode|Ficheiro '''App.java'''| | ||
− | < | + | <source lang="java"> |
public class App { | public class App { | ||
− | + | /** | |
− | + | * @param args | |
− | + | */ | |
− | + | public static void main(String[] args) { | |
− | + | Taxpayer c1 = new Company(); | |
− | + | Taxpayer r1 = new Region(); | |
− | + | Taxpayer p1 = new Person(); | |
− | + | ||
− | + | FriendlyIRS vt = new VanillaTaxes(); | |
− | + | FriendlyIRS ct = new BecauseWeCare(); | |
− | + | ||
− | + | System.out.println("Company taxes (vanilla): " + c1.accept(vt)); | |
− | + | System.out.println("Region taxes (vanilla): " + r1.accept(vt)); | |
− | + | System.out.println("Person taxes (vanilla): " + p1.accept(vt)); | |
− | + | System.out.println("Company taxes (care): " + c1.accept(ct)); | |
− | + | System.out.println("Region taxes (care): " + r1.accept(ct)); | |
− | + | System.out.println("Person taxes (care): " + p1.accept(ct)); | |
− | + | } | |
} | } | ||
− | </ | + | </source> |
}} | }} | ||
Line 331: | Line 331: | ||
== Compiling == | == Compiling == | ||
− | + | javac App.java | |
== Running == | == Running == |
Uma agência de cobrança de impostos tornou-se famosa por permitir adaptar métodos de cobrança de impostos de forma muito flexível. Os contribuintes (Taxpayer) são pessoas (Person), empresas (Company) e regiões (Region). As pessoas trabalham nas empresas e as empresas estão sediadas em regiões. Todos têm rendimentos (as pessoas e as regiões a partir das empresas e as empresas a partir de pessoas, regiões e outras empresas) e todos devem pagar os seus impostos.
O sucesso da agência advém da facilidade com que cria variações do seu produto, o premiado FriendlyIRS. Estas aplicações permitem interrogar cada contribuinte de forma adaptada, tanto ao contribuinte, como à situação de cobrança desejada.
Assim, além da cobrança em habitual, através do seu produto VanillaTaxes, permite ainda cobrar menos impostos se o rendimento for menor que um dado valor ou se a população (número de contribuintes numa empresa ou numa região) for inferior a um dado valor de referência. Para isso, disponibiliza o seu produto BecauseWeCare.
Implemente todas as classes mencionadas:
Crie um exemplo (main) que ilustre a aplicação das diferentes classes.
Ficheiro Taxpayer.java |
---|
/**
* Basic taxpayer.
*/
public abstract class Taxpayer {
/**
* No actual value is returned in this case.
*
* @param irs
* the visitor used to compute the revenue.
* @return tax payed by this taxpayer.
*/
public double accept(FriendlyIRS irs) {
throw new UnsupportedOperationException();
}
}
|
Ficheiro Person.java |
---|
/**
* Individual taxpayer.
*
* We omitted the initialisation code.
*/
public class Person extends Taxpayer {
/**
* @see Taxpayer#accept(FriendlyIRS)
*/
@Override
public double accept(FriendlyIRS irs) {
return irs.taxPerson(this);
}
}
|
Ficheiro Company.java |
---|
import java.util.ArrayList;
/**
* A company has employees (persons).
*
* We omitted the initialisation code.
*/
public class Company extends Taxpayer {
/**
* The employees in this company.
*/
private ArrayList<Person> _employees = new ArrayList<Person>();
/**
* Simple constructor for initialising the company with some employees.
*/
public Company() {
int count = (int) (Math.random() * 100);
for (int i = 0; i < count; i++)
_employees.add(new Person());
}
/**
* @return size of company (number of employees).
*/
public int size() {
return _employees.size();
}
/**
* @param index
* @return an employee
*/
public Person getEmployee(int index) {
return _employees.get(index);
}
/**
* @see Taxpayer#accept(FriendlyIRS)
*/
@Override
public double accept(FriendlyIRS irs) {
return irs.taxCompany(this);
}
}
|
Ficheiro Region.java |
---|
import java.util.ArrayList;
/**
* A region has companies.
*
* We omitted the initialisation code.
*/
public class Region extends Taxpayer {
/**
* The companies in this region.
*/
private ArrayList<Company> _companies = new ArrayList<Company>();
/**
* Simple constructor for initialising the region with some companies.
*/
public Region() {
int count = (int) (Math.random() * 100);
for (int i = 0; i < count; i++)
_companies.add(new Company());
}
/**
* @return size of region (number of companies).
*/
public int size() {
return _companies.size();
}
/**
* @param index
* @return a company
*/
public Company getCompany(int index) {
return _companies.get(index);
}
/**
* @see Taxpayer#accept(FriendlyIRS)
*/
@Override
public double accept(FriendlyIRS irs) {
return irs.taxRegion(this);
}
}
|
The abstract class representing the concept of tax computation.
Ficheiro FriendlyIRS.java |
---|
/**
* The IRS computing visitor interface.
*/
public abstract class FriendlyIRS {
/**
* @param person
* @return tax payed by this person.
*/
public abstract double taxPerson(Person person);
/**
* @param company
* @return tax payed by this company.
*/
public abstract double taxCompany(Company company);
/**
* @param region
* @return tax payed by this region.
*/
public abstract double taxRegion(Region region);
}
|
Simple tax computation.
Ficheiro VanillaTaxes.java |
---|
/**
* Usual tax calculator.
*/
public class VanillaTaxes extends FriendlyIRS {
/**
* @see FriendlyIRS#taxCompany(Company)
*/
@Override
public double taxCompany(Company company) {
double tax = 0;
for (int index = 0; index < company.size(); index++)
tax += company.getEmployee(index).accept(this);
return tax;
}
/**
* @see FriendlyIRS#taxPerson(Person)
*/
@Override
public double taxPerson(Person person) {
return 1;
}
/**
* @see FriendlyIRS#taxRegion(Region)
*/
@Override
public double taxRegion(Region region) {
double tax = 0;
for (int index = 0; index < region.size(); index++)
tax += region.getCompany(index).accept(this);
return tax;
}
}
|
Discounted taxes.
Ficheiro BecauseWeCare.java |
---|
/**
* The discount tax system.
*/
public class BecauseWeCare extends FriendlyIRS {
/**
* Low water marker for revenue.
*/
private final int LOW = 1;
/**
* Low water marker for population.
*/
private final int POP = 50;
/**
* @see FriendlyIRS#taxCompany(Company)
*/
@Override
public double taxCompany(Company company) {
double tax = 0;
for (int index = 0; index < company.size(); index++)
tax += company.getEmployee(index).accept(this);
if (company.size() < POP || tax < LOW)
tax *= .9;
return tax;
}
/**
* In this case, we chose not to test the LOW level (simply because we know
* the value is the same).
*
* @see FriendlyIRS#taxPerson(Person)
*/
@Override
public double taxPerson(Person person) {
return 1;
}
/**
* @see FriendlyIRS#taxRegion(Region)
*/
@Override
public double taxRegion(Region region) {
double tax = 0;
for (int index = 0; index < region.size(); index++)
tax += region.getCompany(index).accept(this);
if (region.size() < POP || tax < LOW)
tax *= .9;
return tax;
}
}
|
Simple demo application.
Ficheiro App.java |
---|
public class App {
/**
* @param args
*/
public static void main(String[] args) {
Taxpayer c1 = new Company();
Taxpayer r1 = new Region();
Taxpayer p1 = new Person();
FriendlyIRS vt = new VanillaTaxes();
FriendlyIRS ct = new BecauseWeCare();
System.out.println("Company taxes (vanilla): " + c1.accept(vt));
System.out.println("Region taxes (vanilla): " + r1.accept(vt));
System.out.println("Person taxes (vanilla): " + p1.accept(vt));
System.out.println("Company taxes (care): " + c1.accept(ct));
System.out.println("Region taxes (care): " + r1.accept(ct));
System.out.println("Person taxes (care): " + p1.accept(ct));
}
}
|
javac App.java
java App
Sample outputs:
Company taxes (vanilla): 21.0 Region taxes (vanilla): 4631.0 Person taxes (vanilla): 1.0 Company taxes (care): 18.900000000000002 Region taxes (care): 4505.800000000001 Person taxes (care): 1.0
Region has some companies with less than the minimum number of employees:
Company taxes (vanilla): 81.0 Region taxes (vanilla): 192.0 Person taxes (vanilla): 1.0 Company taxes (care): 81.0 Region taxes (care): 172.8 Person taxes (care): 1.0