• 用最简单的例子说明设计模式(三)之责任链、建造者、适配器、代理模式、享元模式


    责任链模式
    一个请求有多个对象来处理,这些对象是一条链,但具体由哪个对象来处理,根据条件判断来确定,如果不能处理会传递给该链中的下一个对象,直到有对象处理它为止
    使用场景
    1)有多个对象可以处理同一个请求,具体哪个对象处理该请求待运行时刻再确定
    2)在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
    3)可动态指定一组对象处理请求,客户端可以动态创建职责链来处理请求
     
    public class Chain {
    
        public abstract class Handler {
            private Handler nextHandler;
            // 当前领导能审批通过的最多天数
            public int maxDay;
    
            protected Handler(int maxDay) {
                this.maxDay = maxDay;
            }
    
            //设置责任链中下一个处理请求的对象
            public void setNextHandler(Handler handler) {
                nextHandler = handler;
            }
    
            protected void handleRequest(int day) {
                if (day <= maxDay) {
                    reply(day);
                } else {
                    if (nextHandler != null) {
                        //审批权限不够,继续上报
                        nextHandler.handleRequest(day);
                    } else {
                        System.out.println("没有更高的领导审批了");
                    }
                }
            }
    
            protected abstract void reply(int day);
        }
    
        class ProjectManager extends Handler {
            public ProjectManager(int day) {
                super(day);
            }
    
            @Override
            protected void reply(int day) {
                System.out.println(day + "天请假,项目经理直接审批通过");
            }
        }
    
        class DepartmentManager extends Handler {
            public DepartmentManager(int day) {
                super(day);
            }
    
            @Override
            protected void reply(int day) {
                System.out.println(day + "天请假,部门经理审批通过");
            }
        }
    
        class GeneralManager extends Handler {
            public GeneralManager(int day) {
                super(day);
            }
    
            @Override
            protected void reply(int day) {
                System.out.println(day + "天请假,总经理直接审批通过");
            }
        }
    
        public static void main(String[] strings) {
            Chain chain = new Chain();
            Handler projectManager = chain.new ProjectManager(3);
            Handler departmentManager = chain.new DepartmentManager(5);
            Handler generalManager = chain.new GeneralManager(15);
            //创建职责链
            projectManager.setNextHandler(departmentManager);
            departmentManager.setNextHandler(generalManager);
            //发起请假请求
            projectManager.handleRequest(4);
        }
    }
    

      

     
     
     
     
    Buidler(建造者)模式
    一种创建型的设计模式.,通常用来将一个复杂的对象的构造过程分离, 让使用者可以根据需要选择创建过程.另外, 当这个复杂的对象的构造包含很多可选参数时, 也可以使用建造者模式
    public class AlerDialog {
    
        private  String title;
        private  String message;
    
        public AlerDialog(Builder builder) {
    //        View.inflate()
            this.title = builder.title;
            this.message = builder.message;
        }
    
        public static class Builder {
            private  String title;
            private  String message;
    
            public  Builder setTitle(String title) {
                this.title = title;
                return this;
            }
    
            public   Builder setMessage(String message) {
                this.message = message;
                return this;
            }
    
            public  AlerDialog build() {
                return new AlerDialog(this);
            }
        }
    }
     new AlerDialog.Builder().setTitle("").setMessage("").build();
    

      

     
    适配器模式
    把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起使用的类能够一起工作。  
    适配器就是一种适配中间件,它存在于不匹配的二者之间,用于连接二者,将不匹配变得匹配,简单点理解就是平常所见的转接头,转换器之类的存在。

    类适配器
    原理:通过继承来实现适配器功能。
    类适配器使用对象继承的方式,是静态的定义方式 
    对于类适配器,适配器可以重定义Adaptee的部分行为,使Adaptee有了sampleOperation2()
    对于类适配器,仅仅引入了一个对象,并不需要额外的引用来间接得 到 Adaptee 
    对于类适配器,由于适配器直接继承了Adaptee,使得适配器不能和 Adaptee的子类一起工作 
    public interface Target {
    
        void sampleOperation1();
    
        void sampleOperation2();
    }
    public class Adaptee {
    
        public void sampleOperation1() {
            System.out.println("sampleOperation1");
        }
    }
    public class Adapter extends Adaptee implements Target {
    
        @Override
        public void sampleOperation2() {
            System.out.println("sampleOperation2");
        }
    
    }
    public class MyClass {
        public static void main(String[] args) {
            Adapter adapter = new Adapter();
            adapter.sampleOperation1();
            adapter.sampleOperation2();
        }
    }
    

      


    对象适配器
    与类的适配器模式一样,对象的适配器模式把被适配的类的API转换成为目标类的API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到Adaptee类,而是使用委派关系连接到Adaptee类。
    对象适配器使用对象组合的方式,是动态组合的方式
    对于对象适配器,一个适配器(adaptee)可以把多种不同的源适配到同一个目标
    对于对象适配器,要重定义Adaptee的行为比较困难
    对于对象适配器,需要额外的引用来间接得到Adaptee。
    public interface Target {
    
        void sampleOperation1();
    
        void sampleOperation2();
    }
    
    public class Adaptee {
        public void sampleOperation1() {
            System.out.println("sampleOperation1");
        }
    }
    
    public class Adapter implements Target {
    
        private Adaptee mAdaptee;
    
        public Adapter(Adaptee adaptee) {
            mAdaptee = adaptee;
        }
    
        @Override
        public void sampleOperation1() {
            mAdaptee.sampleOperation1();
        }
    
        @Override
        public void sampleOperation2() {
            System.out.println("sampleOperation2");
        }
    
    }
    
    public class MyClass {
    
        public static void main(String[] args) {
            Adapter adapter =new Adapter(new Adaptee());
            adapter.sampleOperation1();
            adapter.sampleOperation2();
        }
    }
    

      

     
     
     
    代理模式
    通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,扩展目标对象的功能。在调用这个方法前作的前置处理(统一的流程代码放到代理中处理)。调用这个方法后做后置处理。
    这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。
    动态代理的用途与装饰模式很相似,就是为了对某个对象进行增强。所有使用装饰者模式的案例都可以使用动态代理来替换。
     
    /**
     * subject(抽象主题角色):
     * 真实主题与代理主题的共同接口。
     */
    interface Subject {
        void sellBook();
    }
    
    /**
     * ReaISubject(真实主题角色):
     * 定义了代理角色所代表的真实对象。
     */
    public class RealSubject implements Subject {
        @Override
        public void sellBook() {
            System.out.println("出版社卖书");
        }
    }
    
    /**
     * Proxy(代理主题角色):
     * 含有对真实主题角色的引用,代理角色通常在将客
     * 户端调用传递给真实主题对象之前或者之后执行某些
     * 操作,而不是单纯返回真实的对象。
     */
    public class ProxySubject implements Subject {
    
        private RealSubject realSubject;
    
        @Override
        public void sellBook() {
            if (realSubject == null) {
                realSubject = new RealSubject();
            }
            sale();
            realSubject.sellBook();
            give();
        }
    
        public void sale() {
            System.out.println("打折");
        }
    
        public void give() {
            System.out.println("送优惠券");
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            //静态代理(我们自己静态定义的代理类)
            ProxySubject proxySubject = new ProxySubject();
            proxySubject.sellBook();
    
            //动态代理(通过程序动态生成代理类,该代理类不是我们自己定义的。而是由程序自动生成)
            RealSubject realSubject = new RealSubject();
            MyHandler myHandler = new MyHandler();
            myHandler.setProxySubject(realSubject);
            Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),
                    realSubject.getClass().getInterfaces(), myHandler);
            subject.sellBook();
    
        }
    }
    
    public class MyHandler implements InvocationHandler {
        private RealSubject realSubject;
    
        public void setProxySubject(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
    
        /**
         * @param proxy   指代我们所代理的那个真实对象
         * @param method   指代的是我们所要调用真实对象的某个方法的Method对象
         * @param args    指代的是调用真实对象某个方法时接受的参数
         * @return
         * @throws Throwable
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            sale();
            proxy = method.invoke(realSubject, args);
            give();
            return proxy;
        }
    
        public void sale() {
            System.out.println("打折");
        }
    
        public void give() {
            System.out.println("送优惠券");
        }
    }
    

      

     
    享元模式
    享元的目的是为了减少不会要额内存消耗,将多个对同一对象的访问集中起来,不必为每个访问者创建一个单独的对象,以此来降低内存的消耗。
    public class FlyWeight {
    
        static class MyString {
            private String myChar;
    
            public MyString(String myChar) {
                this.myChar = myChar;
            }
    
    
            public void display() {
                System.out.println(myChar);
            }
        }
    
        static class MyCharacterFactory {
    
            private Map<String, MyString> pool;
    
            public MyCharacterFactory() {
                pool = new HashMap<>();
            }
    
            public MyString getMyCharacte(String strig) {
                MyString myString = pool.get(strig);
                if (myString == null) {
                    myString = new MyString(strig);
                    pool.put(strig, myString);
                }
                return myString;
            }
        }
    
        public static void main(String[] args) {
            MyCharacterFactory myCharacterFactory = new MyCharacterFactory();
            MyString a = myCharacterFactory.getMyCharacte("a");
            MyString b = myCharacterFactory.getMyCharacte("b");
            MyString a1 = myCharacterFactory.getMyCharacte("a");
            MyString d = myCharacterFactory.getMyCharacte("d");
    
            if (a == a1) {
                System.out.println("true");
            }
    
        }
    }
    

      

  • 相关阅读:
    Domino+Qucikplace+Sametime构建企业办公平台图文攻略(一)
    GridPanel如果不设宽度,在IE下会变得很宽问题解决
    Domino+Qucikplace+Sametime构建企业办公平台图文攻略(二)
    extjs可视化开发工具
    JSON
    Domino的命名空间
    封装的ExtGrid 实现增、删、改、查等功能
    lotus 附件的存、 取 、删
    asp.net DateTime的使用
    SQL Server里面可能经常会用到的日期格式转换方法
  • 原文地址:https://www.cnblogs.com/sixrain/p/9021641.html
Copyright © 2020-2023  润新知