PECS:如何将消费者转变为生产者?
PECS: How to convert a Consumer to a Producer?
我有一家生产餐点的餐厅。厨房里的盘子是消费者。
class Food{}
class Bamboo extends Food {}
interface Kitchen {
void build(List<? super Food> dessert);
}
abstract class Restaurant {
Kitchen kitchen;
public Restaurant(Kitchen kitchen) {
this.kitchen = kitchen;
}
List<? extends Food> getMeals() {
List<Food> food = new ArrayList<>();
this.kitchen.build(food);
return food;
}
}
class PandaKitchen implements Kitchen{
// Exact signature of the Kitchen
@Override
public void build(List<? super Food> plate) {
// the List IS a consumer of bamboos
plate.add(new Bamboo());
}
}
// Bamboo specialized restaurant
class OhPanda extends Restaurant {
public OhPanda() {
super(new PandaKitchen());
}
// Specialized signature of List<? extends Food>
@Override
List<Bamboo> getMeals() {
List<? super Food> bamboos = new ArrayList<>();
this.kitchen.build(bamboos);
// Obviously here, there is no information of having only Bamboos
return bamboos; // <==== FAIL
//return (List<Bamboo>) bamboos; // would not compile
}
}
在最后一行,我知道我的 OhPanda 餐厅只生产 Bamboos。在内存中没有 creating/copying ArrayList 的情况下转换我的 List<? super Food>
的最佳做法是什么?
这里写了一个更完整的要点:https://gist.github.com/nicolas-zozol/8c66352cbbad0ab67474a776cf007427
我认为您错误地使用了下界通配符。通过在实现中不指定通配符的 Class,您可以将其用作可能面临的上界通配符限制的转折点。我认为你不想处理食物及其超类型。您只想使用 Food 及其衍生物,您应该使用“?extends Food”找到解决方案,甚至摆脱通配符并使用 List< Food >
或者,也许你可以写一个餐厅和厨房的打字版本?
package kitchen;
import java.util.ArrayList;
import java.util.List;
class Food{}
class Bamboo extends Food {}
interface Kitchen<F> {
void build(List<F> dessert);
}
abstract class Restaurant<T> {
protected Kitchen kitchen;
Restaurant(Kitchen kitchen) {
this.kitchen = kitchen;
}
List<T> getMeals() {
List<T> food = new ArrayList<>();
kitchen.build(food);
return food;
}
}
class PandaKitchen implements Kitchen<Bamboo>{
@Override
public void build(List<Bamboo> dessert)
{
dessert.add(new Bamboo());
}
}
/** Bamboo specialized restaurant*/
class OhPanda extends Restaurant<Bamboo> {
OhPanda() {
super(new PandaKitchen());
}
@Override
List<Bamboo> getMeals() {
List<Bamboo> bamboos = new ArrayList<>();
kitchen.build(bamboos);
return bamboos;
}
}
我有一家生产餐点的餐厅。厨房里的盘子是消费者。
class Food{}
class Bamboo extends Food {}
interface Kitchen {
void build(List<? super Food> dessert);
}
abstract class Restaurant {
Kitchen kitchen;
public Restaurant(Kitchen kitchen) {
this.kitchen = kitchen;
}
List<? extends Food> getMeals() {
List<Food> food = new ArrayList<>();
this.kitchen.build(food);
return food;
}
}
class PandaKitchen implements Kitchen{
// Exact signature of the Kitchen
@Override
public void build(List<? super Food> plate) {
// the List IS a consumer of bamboos
plate.add(new Bamboo());
}
}
// Bamboo specialized restaurant
class OhPanda extends Restaurant {
public OhPanda() {
super(new PandaKitchen());
}
// Specialized signature of List<? extends Food>
@Override
List<Bamboo> getMeals() {
List<? super Food> bamboos = new ArrayList<>();
this.kitchen.build(bamboos);
// Obviously here, there is no information of having only Bamboos
return bamboos; // <==== FAIL
//return (List<Bamboo>) bamboos; // would not compile
}
}
在最后一行,我知道我的 OhPanda 餐厅只生产 Bamboos。在内存中没有 creating/copying ArrayList 的情况下转换我的 List<? super Food>
的最佳做法是什么?
这里写了一个更完整的要点:https://gist.github.com/nicolas-zozol/8c66352cbbad0ab67474a776cf007427
我认为您错误地使用了下界通配符。通过在实现中不指定通配符的 Class,您可以将其用作可能面临的上界通配符限制的转折点。我认为你不想处理食物及其超类型。您只想使用 Food 及其衍生物,您应该使用“?extends Food”找到解决方案,甚至摆脱通配符并使用 List< Food >
或者,也许你可以写一个餐厅和厨房的打字版本?
package kitchen;
import java.util.ArrayList;
import java.util.List;
class Food{}
class Bamboo extends Food {}
interface Kitchen<F> {
void build(List<F> dessert);
}
abstract class Restaurant<T> {
protected Kitchen kitchen;
Restaurant(Kitchen kitchen) {
this.kitchen = kitchen;
}
List<T> getMeals() {
List<T> food = new ArrayList<>();
kitchen.build(food);
return food;
}
}
class PandaKitchen implements Kitchen<Bamboo>{
@Override
public void build(List<Bamboo> dessert)
{
dessert.add(new Bamboo());
}
}
/** Bamboo specialized restaurant*/
class OhPanda extends Restaurant<Bamboo> {
OhPanda() {
super(new PandaKitchen());
}
@Override
List<Bamboo> getMeals() {
List<Bamboo> bamboos = new ArrayList<>();
kitchen.build(bamboos);
return bamboos;
}
}