zoukankan      html  css  js  c++  java
  • JAVA混型和潜在类型机制

    一、混型

    ①、定义 

    二、利用JAVA如何实现混型

    ①、代理   ②、装饰器模式  ③、动态代理模式   ④、装饰器模式与代理模式的区别

    三、潜在类型机制

    ①、定义

    四、JAVA的潜在类型机制的补偿

    ①、实现类与类之间的方法共用(反射机制)。。。讲述其使用过程。。。及其缺点

    ②、实现序列(List,Queue)之间方法的共用。。。讲述其使用过程。。。及其缺点

    ③、实现Collection之间方法的共用。。。讲述其使用过程。。。及其缺点

    ④、实现一般化的方法共用(适配器模式)。。。讲述其使用过程。。及其缺点

    ⑤、实现优雅的一般化的方法共用(策略模式)。。。讲述其使用过程。。。

    回答:

    一、混型

    就是一个类混合了多个类的能力。  当想在混型类中修改某些东西,这些修改会应用于混型的所有类型上。

    二、实现混型

    ①、代理机制

    步骤:1、创建混型接口  2、创建接口的具体实现  3、创建混型类,类中持有混型。

    首先 创建混型接口

    public interface Fly{
        void fly();
    }    
    Fly

    其次,创建接口的具体实现

    public Swing implements Fly{
        public void fly(){
          System.out.println("I can use swing to fly"); 
        }
    }    
    Swing

    最后创建具体混型类

    public class Duck implements Fly{
        private Swing mSwim = new Swing();
        
        public void fly(){
            mSwim.fly();
        }
        
        public void swim(){
            System.out.println("I can swim");
        }
    }
    Duck

    缺点:当使用复杂的混型,代码量会急剧上升。

    ②、装饰器模式

    步骤:1、创建被装饰对象(可以是类也可以是接口,最好是接口 这里我用的是接口) 2、创建被装饰对象继承装饰接口  3、创建装饰器(装饰器中包含装饰对象)

    1、创建装饰接口

    public interface Basket {
        void show();
    }
    Basket

    2、继承装饰接口,为被装饰对象

    public class Original implements Basket{
    
        @Override
        public void show() {
            // TODO Auto-generated method stub
            System.out.println("I am a Basket");
        }
    
    }
    Original

    3、创建装饰器(Apple,Banana,Orange)

    public class AppleDecorator implements Basket{
        private Basket mBasket;
        public Apple(Basket basket) {
            // TODO Auto-generated constructor stub
            mBasket = basket;
        }
        @Override
        public void show() {
            // TODO Auto-generated method stub
            mBasket.show();
            System.out.println("Apple");
        }
    }
    AppleDecorator
    public class BananaDecorator implements Basket{
        private Basket mBasket;
        public Banana(Basket basket) {
            // TODO Auto-generated constructor stub
            mBasket = basket;
        }
        @Override
        public void show() {
            // TODO Auto-generated method stub
            mBasket.show();
            System.out.println("Banana");
        }
    }
    BananaDecorator

    其他略

    4、使用装饰器

    public class Main {
        public static void main(String[]args){
            Original original = new Original();
            Basket basket = new Apple(new Banana(new Orange(original)));
            basket.show();
        }
    }
    Main

    缺点:只有效作用于装饰的最后一层。

    ③、动态代理

    步骤:1、创建接口  2、创建接口的具体实现  3、创建Proxy类 4、使用Proxy类

    ①、创建接口

    public interface Business {
        void doSomething();
        void doSomeElse();
    }
    Business

    ②、实现接口

    public class RealObject implements Business{
    
        @Override
        public void doSomething() {
            // TODO Auto-generated method stub
            printf("Do some better things");
        }
    
        @Override
        public void doSomeElse() {
            // TODO Auto-generated method stub
            printf("Anything i can do it");
        }
        
        public static void printf(String str){
            System.out.println(str);
        }
    
    }
    RealObject

    ③、创建代理类

    public class BusinessProxy implements InvocationHandler{
        private Object mData;
        public BusinessProxy(Object dataObject) {
            // TODO Auto-generated constructor stub
            mData = dataObject;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // TODO Auto-generated method stub
            System.out.println("No one thing I can do");
            return method.invoke(mData, args);
        }
    }
    BusinessProxy

    ④、启动代理

    public class Main {
        public static void main(String[] args){
            RealObject object = new RealObject();
            Business proxy = (Business)Proxy.newProxyInstance(Business.class.getClassLoader(), new Class[]{Business.class},new BusinessProxy(object));
            proxy.doSomething();
        }
    }
    Main

    ④、

    装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。当我们使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。

    JAVA潜在类型机制

    1、什么叫做潜在类型机制

    在C++和python中,可以不知道当前类的类型,就可以调用方法。

    ①、JAVA如何补偿(反射机制)

    步骤 1、建立两个类,其有相同的方法

    public class TypeOne {
        private int data = 1;
        
        public void setData(int data){
            this.data = data;
        }
        
        public int getData() {
            return data;
        }
    }
    TypeOne
    public class TypeTwo {
        private int data = 2;
        public void setData(int data){
            this.data = data;
        }
        
        public int getData(){
            return data;
        }
    }
    TypeTwo

    2、利用反射调用,相同的方法

    public class Main {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            TypeOne typeOne = new TypeOne();
            TypeTwo typeTwo = new TypeTwo();
            //调用反射方法,实现不同类可以通过一个方法调用相同的方法
            getData(typeOne);
            getData(typeTwo);
        }
        
        //实现反射的方法
        public static void getData(Object type){
            Class<?> c = type.getClass();
            try {
                //获取叫做getData()的方法
                Method method = c.getMethod("getData");
                //调用该方法
                int data = (int) method.invoke(type,null);
                //输出
                System.out.println(type.getClass().getSimpleName()+"  data:"+data);
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    Main

    缺点:只能在类与类之间使用。

    ②、序列中调用相同的方法

    步骤1、创建fill()方法,传入迭代器,通过反射调用序列中对象的方法

    public class Full{
          //通过泛型,传入 迭代器,和具体需要调用的方法名,及参数
        public static <T,S extends Iterable<T>> void fill(S sql,Method method,Object...args){
                    //获取迭代器
            Iterator<T> iterator = sql.iterator();
            while(iterator.hasNext()){
                T object = iterator.next();
                try {
                                    //调用方法
                    method.invoke(object, args);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }            
    Full

    步骤2、创建调用对象

    public class Apple {
        private static int count = 1;
        private final int id = count++;
        
        public void getId(){
            System.out.println(id);
        }
    }
    Apple

    步骤3、使用方法

        public static void main(String[] args){
            ArrayList<Apple> list = new ArrayList<>();
            for(int i=0; i<10; ++i){
                list.add(new Apple());
            }
            try {
                fill(list, Apple.class.getMethod("getId"),null);
            } catch (NoSuchMethodException | SecurityException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    Full

    个人理解:就是将传入的参数变成了迭代器而已。

    缺点:只能在含迭代器的序列中使用。

    ③、在Colleciotn中调用add()方法

    同:只是将传入的参数直接变成Collection了而已

    ④、通过适配器使用潜在类型

    步骤1、创建适配的接口

    public interface Addable<T> {
        void add(T data);
    }
    Addable

    步骤2、创建适配器

    public class AddableAdapter<T> implements Addable<T> {
        private Collection<T> collection;
        public AddableAdapter(Collection<T> col) {
            // TODO Auto-generated constructor stub
            this.collection = col;
        }
        @Override
        public void add(T data) {
            // TODO Auto-generated method stub
            collection.add(data);
        }
    
    
    }
    AddableAdapter

    步骤3、使用适配器。

    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            List<Integer> list = new ArrayList<>();
            AddableAdapter<Integer> adapter = new AddableAdapter<>(list);
            adapter.add(10);
            for(int i : list){
                System.out.println(i);
            }
        }
    
    }
    Main

    ⑤、通过策略模式一般化潜在类型

    步骤1、创建策略接口

    步骤2、继承策略接口

    步骤3、创建功能类

    步骤4、调用

    个人理解:策略接口的具体实现就是Collection类中对象共有的方法。   功能类的方法,就是对共有方法的调用。

  • 相关阅读:
    李洪强经典面试题43
    李洪强经典面试题42
    李洪强经典面试题41-iOS选择题
    HTTP头部解析
    iOS
    内网安全工具之hscan扫描
    跟着百度学PHP[4]OOP面对对象编程-17-多态
    绕过注入学习笔记
    引用/别名
    跟着百度学PHP[4]OOP面对对象编程-16-switch逻辑就语句
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5700795.html
Copyright © 2011-2022 走看看