我正在查看反应流规范的Publisher(AsyncIterablePublisher.java)的示例实现,当我偶然发现了一些我不明白为什么会这样做的事情。
enum Signal {
Cancel,
Subscribe,
Send;
}
说实话,我不是那么高级程序员,而是写这篇文章的人,我确信有理由这样做。但是我也无法解释为什么它会比这更好(这就是我要做的)。
package com.androidhub4you.multilevellistview;
import java.util.ArrayList;
import com.androidhub4you.multilevellistview.Product.SubCategory;
import com.androidhub4you.multilevellistview.Product.SubCategory.ItemList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
*
* @author manish
*
*/
public class MainActivity extends Activity {
private ArrayList<Product>pProductArrayList;
private ArrayList<SubCategory>pSubItemArrayList;
private ArrayList<SubCategory>pSubItemArrayList2;
private LinearLayout mLinearListView;
boolean isFirstViewClick=false;
boolean isSecondViewClick=false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLinearListView = (LinearLayout) findViewById(R.id.linear_listview);
/**
*
*/
ArrayList<ItemList> mItemListArray=new ArrayList<ItemList>();
mItemListArray.add(new ItemList("Red", "20"));
mItemListArray.add(new ItemList("Blue", "50"));
mItemListArray.add(new ItemList("Red", "20"));
mItemListArray.add(new ItemList("Blue", "50"));
ArrayList<ItemList> mItemListArray2=new ArrayList<ItemList>();
mItemListArray2.add(new ItemList("Pant", "2000"));
mItemListArray2.add(new ItemList("Shirt", "1000"));
mItemListArray2.add(new ItemList("Pant", "2000"));
mItemListArray2.add(new ItemList("Shirt", "1000"));
mItemListArray2.add(new ItemList("Pant", "2000"));
mItemListArray2.add(new ItemList("Shirt", "1000"));
/**
*
*/
pSubItemArrayList=new ArrayList<SubCategory>();
pSubItemArrayList2=new ArrayList<SubCategory>();
pSubItemArrayList.add(new SubCategory("Color", mItemListArray));
pSubItemArrayList2.add(new SubCategory("Cloths", mItemListArray2));
pSubItemArrayList.add(new SubCategory("Color", mItemListArray));
pSubItemArrayList2.add(new SubCategory("Cloths", mItemListArray2));
/**
*
*/
pProductArrayList=new ArrayList<Product>();
pProductArrayList.add(new Product("Emotions", pSubItemArrayList));
pProductArrayList.add(new Product("Garments", pSubItemArrayList2));
/***
* adding item into listview
*/
for (int i = 0; i < pProductArrayList.size(); i++) {
LayoutInflater inflater = null;
inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mLinearView = inflater.inflate(R.layout.row_first, null);
final TextView mProductName = (TextView) mLinearView.findViewById(R.id.textViewName);
final RelativeLayout mLinearFirstArrow=(RelativeLayout)mLinearView.findViewById(R.id.linearFirst);
final ImageView mImageArrowFirst=(ImageView)mLinearView.findViewById(R.id.imageFirstArrow);
final LinearLayout mLinearScrollSecond=(LinearLayout)mLinearView.findViewById(R.id.linear_scroll);
if(isFirstViewClick==false){
mLinearScrollSecond.setVisibility(View.GONE);
mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
}
else{
mLinearScrollSecond.setVisibility(View.VISIBLE);
mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
}
mLinearFirstArrow.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(isFirstViewClick==false){
isFirstViewClick=true;
mImageArrowFirst.setBackgroundResource(R.drawable.arw_down);
mLinearScrollSecond.setVisibility(View.VISIBLE);
}else{
isFirstViewClick=false;
mImageArrowFirst.setBackgroundResource(R.drawable.arw_lt);
mLinearScrollSecond.setVisibility(View.GONE);
}
return false;
}
});
final String name = pProductArrayList.get(i).getpName();
mProductName.setText(name);
/**
*
*/
for (int j = 0; j < pProductArrayList.get(i).getmSubCategoryList().size(); j++) {
LayoutInflater inflater2 = null;
inflater2 = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mLinearView2 = inflater2.inflate(R.layout.row_second, null);
TextView mSubItemName = (TextView) mLinearView2.findViewById(R.id.textViewTitle);
final RelativeLayout mLinearSecondArrow=(RelativeLayout)mLinearView2.findViewById(R.id.linearSecond);
final ImageView mImageArrowSecond=(ImageView)mLinearView2.findViewById(R.id.imageSecondArrow);
final LinearLayout mLinearScrollThird=(LinearLayout)mLinearView2.findViewById(R.id.linear_scroll_third);
if(isSecondViewClick==false){
mLinearScrollThird.setVisibility(View.GONE);
mImageArrowSecond.setBackgroundResource(R.drawable.arw_lt);
}
else{
mLinearScrollThird.setVisibility(View.VISIBLE);
mImageArrowSecond.setBackgroundResource(R.drawable.arw_down);
}
mLinearSecondArrow.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(isSecondViewClick==false){
isSecondViewClick=true;
mImageArrowSecond.setBackgroundResource(R.drawable.arw_down);
mLinearScrollThird.setVisibility(View.VISIBLE);
}else{
isSecondViewClick=false;
mImageArrowSecond.setBackgroundResource(R.drawable.arw_lt);
mLinearScrollThird.setVisibility(View.GONE);
}
return false;
}
});
final String catName = pProductArrayList.get(i).getmSubCategoryList().get(j).getpSubCatName();
mSubItemName.setText(catName);
/**
*
*/
for (int k = 0; k < pProductArrayList.get(i).getmSubCategoryList().get(j).getmItemListArray().size(); k++) {
LayoutInflater inflater3 = null;
inflater3 = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View mLinearView3 = inflater3.inflate(R.layout.row_third, null);
TextView mItemName = (TextView) mLinearView3.findViewById(R.id.textViewItemName);
TextView mItemPrice = (TextView) mLinearView3.findViewById(R.id.textViewItemPrice);
final String itemName = pProductArrayList.get(i).getmSubCategoryList().get(j).getmItemListArray().get(k).getItemName();
final String itemPrice = pProductArrayList.get(i).getmSubCategoryList().get(j).getmItemListArray().get(k).getItemPrice();
mItemName.setText(itemName);
mItemPrice.setText(itemPrice);
mLinearScrollThird.addView(mLinearView3);
}
mLinearScrollSecond.addView(mLinearView2);
}
mLinearListView.addView(mLinearView);
}
}
}
有人可以向我解释为什么会更好吗?优点/缺点?
答案 0 :(得分:2)
不要太严格,这里是我对这段代码的解释。让我们称之为反应流Roland的所有者。
首先,Roland需要一个适用于所有inboundSignals
static interface Signal {};
ConcurrentLinkedQueue<Signal> inboundSignals = new ConcurrentLinkedQueue<Signal>();
Cancel
,Subscribe
和Send
之类的信号始终具有相同的目的是不可变的并经常发生,因此将它们实现为Joshua Bloch's Singleton是一个好主意:< / p>
enum Cancel implements Signal { Instance; };
enum Subscribe implements Signal { Instance; };
enum Send implements Signal { Instance; };
另一种做同样的方式与你的建议和我最喜欢的方式类似:
enum CommonSignals implements Signal{
Cancel {
@Override
void debug() {
System.out.println("Cancel");
}
},
Subscribe {
@Override
void debug() {
System.out.println("Subscribe");
}
},
Send {
@Override
void debug() {
System.out.println("Send");
}
};
abstract void debug();
[...] some other methods I could need in the future
}
如您所见,这是一个不同的实现。但这个想法是一样的 - 信号为单身
我们继续找到这段代码:
static final class Request implements Signal {
final long n;
Request(final long n) { // every Request has different value of n
this.n = n;
}
};
由于inboundSignals
可以包含多个Request
个对象,因此无法将此类型的信号实现为Singleton。因此,它不能是CommonSignals
的成员或实施为enum
。
<强>结论强>
Roland使用了许多可能性之一来实现单身人士。我认为这更像是一种品味如何去做。
答案 1 :(得分:1)
对于AsyncIterablePublisher中的用法类型,两种形式是等价的,可以说后者,一个带有多个常量的枚举,更自然。
实际上,前一种形式非常罕见。我可以看到一个支持使用它的论点(但是很少见,这意味着这一点通常不那么重要):当你在自己的枚举中定义每个常量时,你有机会定义不同的方法/字段,例如:
enum Cancel implements Signal { Instance; };
enum Send implements Signal {
Instance;
public void someSendSpecificMethod() { ... }
}
所以你现在可以做Send.Instance.someSendSpecificMethod()
。非常尴尬,非常罕见。
答案 2 :(得分:1)
不同之处在于您可以在不更改原始枚举的情况下添加另一个Signal实例。您的代码可以使用Signal实例,并且可以提供不同的类型。与类的接口相同 - 为您提供了灵活性,但仅在您需要它时才有用。在你的情况下,我没有看到太多用途,因为界面是空的,实现它的枚举没有任何内容。
您可以查看此站点以获取包含接口的枚举的一个很好的示例:
http://www.selikoff.net/2011/06/15/java-enums-can-implement-interfaces/
答案 3 :(得分:0)
因为我不知道批准哪个答案,所以我邮寄了这段代码的作者并询问了他对此的看法。这是对话(块是来自他。普通文本是我的):
嗨,迈克尔,
那么只有一个枚举有什么区别?你不会有三个单身,但仍然有三个唯一定义的对象。:
当然,那可以做到,但是我必须为它创造一个名字 (比如ConcreteSignal),我选择的编码避免了:)
enum Signal {
Cancel, Subscribe, Send;
}
我认为这也是线程安全的,如果你真的想要拥有共享接口,例如你可以与对象共享,你可以这样做:
enum ConcreteSignal implements Signal {
Cancel,
Subscribe,
Send;
}
你绝对可以像上面那样做,但我认为 他们[取消,订阅,发送]并不比请求更具体 (这也是一个信号): https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.0/examples/src/main/java/org/reactivestreams/example/unicast/AsyncIterablePublisher.java#L49
此外,这也可以鼓励使用Enum的方法 枚举所有可能的信号,它不能,因为请求是 不是信号。有意义吗?
确实在Scala中你更愿意使用Object,但在Java中很少见到类似你的实现。我很好奇我在Java中缺少一些简洁的功能。但是,如果我理解正确,那是因为你更接近Scala,因为它更接近你的首选语言Scala?
我想这有一点,但单身作为枚举模式 在Java中是众所周知的,所以唯一“奇怪”的事情就是 每个取消,订阅和发送都有一个独特的“枚举”,但是 我之前解释过,因为请求不能像我那样编码 选择了更多“Scala-y”版本。
因此,如果“请求”不需要任何参数,我就像你一样 建议:枚举信号{取消,请求,订阅,发送}
神秘解决了: - )。
答案 4 :(得分:0)
我认为使用enum接口的唯一原因是,某些信号的数据与其他信号不同,因此需要扩展枚举类型以将数据附加到其中。