设计模式 --- 适配器模式 Adapter Pattern

设计模式 --- 适配器模式 Adapter Pattern

  • 什么是适配器模式
  • 类适配器 ClassAdapter
  • 对象适配器 ObjectAdapter
  • 接口适配器模式
  • 适配器模式在安卓开发中的例子
    • RecyclerView
    • ListView

什么是适配器模式

  • 适配器可以使两个接口兼容, 也就是通过一个接口实现另外一个接口的方法
  • 比如现在有一个接口叫 AnimalRobot, 并且有两个方法: cry() 和 move. 还有一个接口叫 Dog, 也有两个方法叫 run() 和 bark(). 现在需要使用Dog实现AnimalRobot接口, 但是两个接口完全不兼容. 此时可以使用适配器实现接口兼容
  • 适配器模式主要由三部分组成
  • Target: 目标接口 (上面的AnimalRobit)
  • Source: 被适配接口. (上面的Dog接口)
  • Adapter: 对Adaptee接口与Target进行适配
  • 假设现在有下面两个接口需要适配

Source 接口及实现类

public interface IAC220 {
	void output220V();
}

public class AC220 implements IAC220 { 
    public int output220V(){
        int output = 220;
        return output;
    }
}

Target目标接口

public interface DC5 {
    int output5V();
}

类适配器 ClassAdapter

  • 适配器与适配者之间是继承(或实现)关系
  • 适配器继承被适配类, 实现目标接口
  • 适配器在重写目标接口的方法里使用父类方法实现适配
  • 缺点: 因为java单继承的缘故,target类必须是接口,以便于Adapter去继承Source并实现target,完成适配的功能,但这样就导致了Adapter里暴露了Source类的方法,使用起来的成本就增加了
public class PowerAdapter extends AC220 implements DC5 {
    @Override
    public int output5V() {
        int output = output220V();
        return (output / 44);
    }
}

对象适配器 ObjectAdapter

  • 对于同样的逻辑,我们在以对象适配器模式实现。我们保留AC220和DC5两个基本类,我们让Adapter持有source类的实例,然后再实现DC5,以这种持有对象的方式来实现适配器功能
public class PowerAdapter implements DC5{
    private AC220 mAC220;

    public PowerAdapter(AC220 ac220){
        this.mAC220 = ac220;
    }

    @Override
    public int output5V() {
        int output = 0;
        if (mAC220 != null) {
            output = mAC220.output220V() / 44;
        }
        return output;
    }
}

接口适配器模式

  • 对于接口适配器模式,我们就不用担着眼于220->5,我们的接口可以有更多的抽象方法
  • android开发中用的很多
public interface DCOutput {
    int output5V();
    int output9V();
    int output12V();
    int output24V();
}

设置一个中间适配器,用于实现默认的接口方法

/**
 * Created by italkbb on 2018/1/24.
 * 这里抽象类其实就写了空方法,等着子类去实现需要的方法。
 */
 
public abstract class PowerAdapter implements DCOutput{
    protected AC220 mAC220;

    public PowerAdapter(AC220 ac220){
        this.mAC220 = ac220;
    }

    @Override
    public int output5V() {
        return mAC220.output220V();
    }

    @Override
    public int output9V() {
        return mAC220.output220V();
    }

    @Override
    public int output12V() {
        return mAC220.output220V();
    }

    @Override
    public int output24V() {
        return mAC220.output220V();
    }
}

这样一来我们就只需要重写父类我们关心的方法了

private void initinterfaceAdapter() {
        // 使用匿名类重写需要重写的方法
        interfaceadapter.PowerAdapter powerAdapter = new PowerAdapter(new AC220()) {
            @Override
            public int output5V() {
                int output = 0;
                if (mAC220 != null) {
                    output = mAC220.output220V() / 44;
                }
                return output;
            }
        };
        powerAdapter.output5V();
    }

适配器模式在安卓开发中的例子

RecyclerView

  • 使用适配器完成自定义cardview
  • 需要将restaurantCardArrayList (也就是ArrayList) 适配RecyclerView
  • 使用对象适配器, source: ArrayList , target: RecyclerView,
  • 使用ArrayList实现target中的onBindViewHolder, onCreateViewHolder等方法
public class RestaurantAdapter extends RecyclerView.Adapter<RestaurantAdapter.Viewholder> implements View.OnClickListener{

    private Context context;
    private ArrayList<RestaurantCard> restaurantCardArrayList;
    private static final String TOKEN = "RO1Oxxrhr0ZE2nvxEvJ0ViejBTWKcLLhPQ7wg6GGPlGiHvjwaLPU2eWlt4myH3BC1CP4RSzIQ7UCFjZ-FBaF_4ToUYHfs6FF6FwipyMuz47xVvlpEr6gDv-2YRQUYnYx";
    private RecyclerViewOnItemClickListener onItemClickListener;

    public class Viewholder extends RecyclerView.ViewHolder {
        private ImageView restaurantImage, starSymbol;
        private TextView restaurantTitle, restaurantContent, restaurantRating;
        private View root;

        public Viewholder(@NonNull View root) {
            super(root);
            this.root = root;

            restaurantImage = root.findViewById(R.id.restaurant_image);
            restaurantTitle = root.findViewById(R.id.restaurant_title);
            restaurantContent = root.findViewById(R.id.restaurant_content);
            restaurantRating = root.findViewById(R.id.rating);
            starSymbol = root.findViewById(R.id.star);
        }
    }

    // Constructor
    public RestaurantAdapter(Context context, ArrayList<RestaurantCard> restaurantCardArrayList) {
        this.context = context;
        this.restaurantCardArrayList = restaurantCardArrayList;
    }

    @NonNull
    @Override
    public RestaurantAdapter.Viewholder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View root = LayoutInflater.from(parent.getContext()).inflate(R.layout.restaurant_cardview_item, parent, false);
        Viewholder vh = new Viewholder(root);
        root.setOnClickListener(this);
        return new RestaurantAdapter.Viewholder(root);
    }

    @Override
    public void onBindViewHolder(@NonNull RestaurantAdapter.Viewholder holder, int position) {
        RestaurantCard model = restaurantCardArrayList.get(position);
        holder.restaurantContent.setText(model.getContent());
        if (model.getTitle().length() > 24){
            model.setTitle(model.getTitle().substring(0, 24) + "...");
        }
        holder.restaurantTitle.setText(model.getTitle());
        holder.starSymbol.setImageResource(R.drawable.ic_baseline_star_24);
        holder.restaurantRating.setText(Float.toString(model.getRating()));

        Log.d("From RestaurentAdapter onBindViewHolder", "glide next");
        if (model.getRestaurantImageUrl().toString().length() != 0) {
            GlideUrl glideUrl = new GlideUrl(model.getRestaurantImageUrl(), new LazyHeaders.Builder()
                    .addHeader("Authorization", " Bearer " + TOKEN)
                    .build());
            Glide.with(this.context).load(glideUrl).into(holder.restaurantImage);
        }
        else {
            Log.d("From RestaurentAdapter onBindViewHolder", "getRestaurantImageUrl() is empty");
        }
        holder.root.setTag(position);
    }

    @Override
    public int getItemCount() {
        return restaurantCardArrayList.size();
    }


    @Override
    public void onClick(View view) {
        if (onItemClickListener != null) {
            // Use getTag() to get data
            onItemClickListener.onItemClickListener(view, (Integer) view.getTag());
        }
    }

    public void setRecyclerViewOnItemClickListener(RecyclerViewOnItemClickListener onItemClickListener) {
        this.onItemClickListener = onItemClickListener;
    }

    public interface RecyclerViewOnItemClickListener {

        void onItemClickListener(View view, int position);

    }

}

将Adapter传入recyclerView使用

RestaurantAdapter restaurantAdapter = new RestaurantAdapter(getActivity(), restaurantCardArrayList);
recyclerView.setAdapter(restaurantAdapter);

ListView

  • 接口适配器模式
  • ArrayAdapter有很多包含很多方法, 比如下面的方法
@Override
    public int getCount() {
        return mObjects.size();
    }

    @Override
    public @Nullable T getItem(int position) {
        return mObjects.get(position);
    }

    /**
     * Returns the position of the specified item in the array.
     *
     * @param item The item to retrieve the position of.
     *
     * @return The position of the specified item.
     */
    public int getPosition(@Nullable T item) {
        return mObjects.indexOf(item);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public @NonNull View getView(int position, @Nullable View convertView,
            @NonNull ViewGroup parent) {
        return createViewFromResource(mInflater, position, convertView, parent, mResource);
    }

使用内部匿名类实现其中需要的方法

listview.setAdapter(new ArrayAdapter<String>(this, R.layout.list_item, list) {
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = super.getView(position, convertView, parent);
                TextView textView = (view.findViewById(R.id.listItem));
                textView.setMinHeight(0);
                textView.setMinimumHeight(0);
                textView.setHeight(height/ items.length);
                return view;
            }
        });

你可能感兴趣的:(设计模式,Design,Pattern,设计模式,适配器模式,java)