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

    责任链模式
    一个请求有多个对象来处理,这些对象是一条链,但具体由哪个对象来处理,根据条件判断来确定,如果不能处理会传递给该链中的下一个对象,直到有对象处理它为止
    使用场景
    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");
            }
    
        }
    }
    

      

  • 相关阅读:
    Codeforces 177G2 Fibonacci Strings KMP 矩阵
    Codeforces Gym100187C Very Spacious Office 贪心 堆
    Codeforces 980F Cactus to Tree 仙人掌 Tarjan 树形dp 单调队列
    AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
    BZOJ3622 已经没有什么好害怕的了 动态规划 容斥原理 组合数学
    NOIP2016提高组Day1T2 天天爱跑步 树链剖分 LCA 倍增 差分
    Codeforces 555C Case of Chocolate 其他
    NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
    NOIP2017提高组Day2T2 宝藏 洛谷P3959 状压dp
    NOIP2017提高组Day1T3 逛公园 洛谷P3953 Tarjan 强连通缩点 SPFA 动态规划 最短路 拓扑序
  • 原文地址:https://www.cnblogs.com/sixrain/p/9021641.html
Copyright © 2011-2022 走看看