Java 代理模式

2019-08-12  本文已影响0人  小石头呢

代理模式:指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象。

一.代理模式的步骤:

//中介类
package swu.xl.day7.AgentHouse;

public class Agent {

    String name;

    public Agent(String name){
        this.name = name;
    }

    //保存代理者
    GetHouseMessage delegate;

    //让代理者返回信息给我
    public String letDelegateDo(){

        return delegate.messageOfHuse();
    }

    //协议
    interface GetHouseMessage{

        //返回房子信息
        String messageOfHuse();
    }
}

//房产公司类
package swu.xl.day7.AgentHouse;

public class HouseManager implements Agent.GetHouseMessage {

    String name;

    public HouseManager(String name){
        this.name = name;
    }

    @Override
    public String messageOfHuse() {
        //房产公司做一系列事情
        //***
        return "西南大学D栋412";
    }
}

//人类
package swu.xl.day7.AgentHouse;

public class Person {

    String name;

    public Person(String name){
        this.name = name;
    }

    public void wantHouse(String houseMessage){
        //得到房子了
        System.out.println(name+"的房子是:"+houseMessage);
    }
}

//模拟过程
package swu.xl.day7.AgentHouse;

public class Process {

    public static void main(String[] args){
        //有一个人小王
        Person xw = new Person("小王");

        //有一个中介
        Agent agent = new Agent("租房子中介");

        //有一个房子管理者
        HouseManager houseManager = new HouseManager("文一地产");
        //中介找到真正做事的
        agent.delegate = houseManager;

        //人发起租房子的行为
        xw.wantHouse(agent.letDelegateDo());
    }
}

这里面还可以有一层代理:人和中介的代理,人有各种联系方式。中介提供规定的联系方式,告诉人找到房子的信息。就需要人统一接受信息的方式,怎么做到的呢;中介提供一个接口用于统一联系方式,人只需要服从这个接口就可以接收到回调的信息。


package swu.xl.day11;

//Person类
//线程中:Agent类
public class AllLineInterfaceToBlockTest {
    public static void main(String[] args) {
        Person person = new Person();
        person.name = "小王";
        person.needHouse();
    }

}

class Person implements Agent.AgentInterface {

    String name;

    public void needHouse(){
        System.out.println(Thread.currentThread().getName());
        Agent agent = new Agent();
        agent.start();
        agent.target = this;
    }

    @Override
    public void callback(String desc) {
        System.out.println(name+"的房子:"+desc);
    }
}

class Agent extends Thread{

    AgentInterface target;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        System.out.println("开始找房子");
        System.out.println("---------");
        System.out.println("房子找到了,返回数据");

        target.callback("西南大学");

        super.run();
    }

    public interface AgentInterface{
        //统一通过打电话的方式告诉人房子的信息
        void callback(String desc);
    }
}

二.为什么需要代理模式

三.优/缺点

优点:

缺点:

四.代理模式使用实例

1.构建一个抽象类作为所有界面的模板,该模板具有两个抽象方法,创建界面和销毁界面;定义一个ArrayList保存添加到该界面的视图;定义一个方法用于添加视图到该界面。

package swu.xl.day6.Teacher;

import java.util.ArrayList;

/**
 * 管理界面的抽象类 定义一个创建界面到结束的模板
 */
public abstract class Activity {

    //保存这个界面的所有子视图
    public ArrayList<View> children = new ArrayList<>();

    //界面创建
    public abstract void onCreate();

    //界面销毁
    public abstract void onDestroy();

    //将子控件添加到界面上
    //接受的时候用父类接受子类
    //当需要访问子类内容的时候,就需要强制转化为对应的类
    public void addChild(View view){

        children.add(view);

        if (view instanceof Button){
            Button button = (Button)view;
            System.out.println(button.title+"按钮被添加到界面上");
        }else {
            ImageView imageView = (ImageView)view;
            System.out.println(imageView.picture+"图片被添加到界面上");
        }
    }
}

2.构建一个View类,拥有一些控件共有的一些属性和方法。该View类想要完成onClick()功能,但是View类很难完成onClick()功能。因为该功能需要主界面来做,所以在View类中写一个Interface,定义好我们想要实现的功能,定义好一个Interface类型的变量用于保存实现类对象。最后定义一个触发事件用于调用实现类对象调用代理方法

package swu.xl.day6.Teacher;

/**
 * 管理视图的显示和事件监听
 * 什么情况下需要讲一个父类做成抽象类(模板)
 * 1.不能直接创建这个类的对象
 * 这个类里面的某些方法还不确定如何实现
 */
public class View {
    //所有的视图都共有的属性
    String backgroundColor;
    String borderColor;

    //记录谁先想监听我这个事件
    //暂时不确定是谁要监听
    //但是要监听的人肯定实现了这个接口
    OnClickeListener listener;

    //所有的视图都需要监听事件
    //定义内部接口,封装
    public interface OnClickeListener{
        //定义一套规范/方法,约束外部使用这些方法来监听事件
        void onClick(View view);
    }

    //用于控件接受触摸事件
    public void getTouchEvent(){
        //调用监听者里面的onClick方法
        listener.onClick(this);
    }
}

3.定义一个继承于ViewButtonImageView

package swu.xl.day6.Teacher;

/**
 * 创建按钮
 */
public class Button extends View {

    String title;
    String titleColor;

    public Button(String title,String titleColor,String backgroundColor,String borderColor){
        this.title = title;
        this.titleColor = titleColor;
        this.backgroundColor = backgroundColor;
        this.borderColor = borderColor;
    }
}
package swu.xl.day6.Teacher;

/**
 * 创建图片
 */
public class ImageView extends View {

    String picture;

    public ImageView(String picture,String backgroundColor,String borderColor){
        this.picture = picture;
        this.backgroundColor = backgroundColor;
        this.borderColor = borderColor;
    }
}

4.定义一个继承于Activity的,实现View.OnClickeListener接口的MainActivity类,在其中实现了接口的方法;在构造方法里面调用onCreate方法用于添加ButtonImageViewButton将其代理者设置为this-MainActivity对象;而ImageView是通过匿名类作为代理者的方式;MainActivity类里面也提供了模拟屏幕触摸的方法。

package swu.xl.day6.Teacher;

/**
 * 主界面(程序运行起来的第一个界面)
 */
public class MainActivity extends Activity implements View.OnClickeListener {

    Button button;
    ImageView imageView;

    //当界面被创建,就自动调用onCreate();
    public MainActivity(){
        onCreate();
    }

    @Override
    public void onCreate() {

        //主界面如何布局

        //添加一个按钮
        button = new Button("分享","红色","","");

        //添加一张图片
        imageView = new ImageView("动漫","","");

        //将创建的控价添加到界面上
        addChild(button);
        addChild(imageView);

        //如果一个控件需要监听事件,那么就必须实现监听事件的接口
        //告诉按钮谁在监听这个事件
        button.listener = this;

        //给imageView添加一个事件监听,匿名对象
        imageView.listener = new View.OnClickeListener() {
            @Override
            public void onClick(View view) {
                System.out.println("图片被点击了");
            }
        };
    }

    //模拟触摸
    public void touch(){
        //将屏幕触摸的事件传递给按钮
        button.getTouchEvent();
        imageView.getTouchEvent();
    }

    @Override
    public void onDestroy() {
        //销毁之前需要做点什么事情
    }

    //当事件触发了,就会调用这个onClick方法
    @Override
    public void onClick(View view) {
        System.out.println("按钮被点击了");
    }
}

5.在main函数里面模拟

package swu.xl.day6.Teacher;

public class MyClass {
    public static void main(String[] args){
        //启动程序 创建界面
        MainActivity main = new MainActivity();

        //模拟触摸
        main.touch();
    }
}

//运行结果
分享按钮被添加到界面上
动漫图片被添加到界面上
按钮被点击了
图片被点击了

五.解析不使用上面的实例的原因

//阅读界面
package swu.xl.day7.NoInterface;

/**
 * 阅读界面,展示显示的文本
 */
public class ReadView {

    private String text;
    private String color;
    private int font;

    public ReadView(String text){
        this.text = text;
    }

    //提供给外部一个方法 可以通过这个方法给我传值
    public void change(String color,int font){
        System.out.println("改变前的颜色:"+this.color+" "+"改变前的颜色:"+this.font);
        this.color = color;
        this.font = font;
        System.out.println("改变后的颜色:"+this.color+" "+"改变后的颜色:"+this.font);
    }
}

//聊天界面
package swu.xl.day7.NoInterface;

public class ChatView {

    private String message;
    private String color;
    private int font;

    public ChatView(String message){
        this.message = message;
    }

    //提供给外部一个方法 可以通过这个方法给我传值
    public void change(String color,int font){
        System.out.println("改变前的颜色:"+this.color+" "+"改变前的颜色:"+this.font);
        this.color = color;
        this.font = font;
        System.out.println("改变后的颜色:"+this.color+" "+"改变后的颜色:"+this.font);
    }
}

//设置界面
package swu.xl.day7.NoInterface;

/**
 * 设置页面 设置字体大小和颜色
 */
public class SetView {

    //记录为谁设置颜色和大小
    //记录下我做完事情之后 将数据返回给谁
    ReadView readView;
    ChatView chatView;

    //开始设置
    public void startSetRead(){
        System.out.println("开始设置");
        System.out.println("........");
        System.out.println("设置完毕 即将返回结果");

        //如果有可以访问属性,直接通过属性给值
        //比较少用 对方没办法第一时间知道自己需要的值

        //通过方法来回调
        readView.change("黑色",30);
    }
    public void startSetChat(){
        System.out.println("开始设置");
        System.out.println("........");
        System.out.println("设置完毕 即将返回结果");

        //通过方法来回调
        chatView.change("白色",50);
    }
}

//模拟过程
package swu.xl.day7.NoInterface;

public class Main {

    public static void main(String[] args){

        //浏览界面
        ReadView readView = new ReadView("test");
        //进入到设置页面
        SetView setView = new SetView();
        setView.readView = readView;
        setView.startSetRead();

        //聊天界面
        ChatView chatView = new ChatView("message");
        //进入到设置页面
        setView.chatView = chatView;
        setView.startSetChat();
    }
}
//阅读界面
package swu.xl.day7.Interface;

public class ReadView implements SetView.SetInterface {

    private String text;
    private String color;
    private int font;

    public ReadView(String text){
        this.text = text;
    }

    @Override
    public void change(String color,int font) {
        System.out.println("改变前的颜色:"+this.color+" "+"改变前的颜色:"+this.font);
        this.color = color;
        this.font = font;
        System.out.println("改变后的颜色:"+this.color+" "+"改变后的颜色:"+this.font);
    }
}

//聊天界面
package swu.xl.day7.Interface;

public class ChatView implements SetView.SetInterface {

    private String message;
    private String color;
    private int font;

    public ChatView(String message){
        this.message = message;
    }

    @Override
    public void change(String color,int font) {
        System.out.println("改变前的颜色:"+this.color+" "+"改变前的颜色:"+this.font);
        this.color = color;
        this.font = font;
        System.out.println("改变后的颜色:"+this.color+" "+"改变后的颜色:"+this.font);
    }
}

//设置界面
public class SetView {

    //保存实现者
    SetInterface setView;

    //开始设置
    public void startSet(){
        System.out.println("开始设置");
        System.out.println("........");
        System.out.println("设置完毕 即将返回结果");

        //通过方法来回调
        setView.change("黑色",30);
    }

    //协议
    interface SetInterface{
        //开始设置界面
        void change(String color,int font);
    }
}

//模拟过程
package swu.xl.day7.Interface;

public class Main {

    public static void main(String[] args){
        //设置页面
        SetView setView = new SetView();

        //浏览界面
        ReadView readView = new ReadView("test");
        //进入到设置页面设置
        setView.setView = readView;
        setView.startSet();

        //浏览界面
        ChatView chatView = new ChatView("message");
        //进入到设置页面设置
        setView.setView = chatView;
        setView.startSet();
    }
}

延伸问题:普通类,抽象类,接口如何选择:

六.进阶学习

标准的代理模式(静态代理和动态代理)

上一篇下一篇

猜你喜欢

热点阅读