zoukankan      html  css  js  c++  java
  • 设计模式

    更新ing

    SOLID原则

    缩写 英文 中文 描写叙述
    SRP The Single Responsibility Principle 单一责任原则 让一个类仅仅做一种类型责任,当这个类须要承当其它类型的责任的时候,就须要分解这个类。
    OCP The Open Closed Principle 开放封闭原则 软件实体应该是可扩展,而不可改动的。也就是说。对扩展是开放的。而对改动是封闭的。
    LSP The Liskov Substitution Principle 里氏替换原则 当一个子类的实例应该能够替换不论什么其超类的实例时,它们之间才具有is-A关系
    DIP The Dependency Inversion Principle 依赖倒置原则 高层模块不应该依赖于低层模块,二者都应该依赖于抽象 2. 抽象不应该依赖于细节,细节应该依赖于抽象
    ISP The Interface Segregation Principle 接口分离原则 不能强迫用户去依赖那些他们不使用的接口。换句话说,使用多个专门的接口比使用单一的总接口总要好

    设计模式

    单例模式Singleton

    定义

    保证一个类仅有一个实例,并提供一个訪问它的全局訪问点。

    扩展:能够创建固定数量的对象。

    本质

    控制实例数目

    长处

    • 节约资源

    缺点

    • 单例是一个虚拟机范围的,由于类装载功能是虚拟机的。对于集群环境,单例模式不适用。

    演示样例

    懒汉式:时间换空间

    public class Singleton {
    
        private static class SingletonHolder {
            private static final Singleton INSTANCE = new Singleton();
        }
    
        private Singleton (){}
    
        public static final Singleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    

    饿汉式:空间换时间

    public class Singleton {
        private static Singleton instance = new Singleton();
        private Singleton() {
        }
        public static Singleton getInstance(){
            return instance;
        }
    }
    

    最佳方案

    public enum Singleton {
    
        instance;
    
        public void operation() {
            // 操作
        }
    }
    

    实际应用场景

    • 读取配置文件
    • 缓存

    抽象工厂Abstract Factory

    定义

    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们详细的类

    本质

    选择产品簇的实现

    长处

    • 分离接口和实现
    • 使得切换产品簇变得easy

    缺点

    • 不太easy扩展新的产品
    • easy造成类层次复杂

    演示样例

    • Abstract Factory:抽象工厂,定义创建一系列产品对象的操作接口
    • Concrete Factory:详细的工厂,实现抽象工厂定义的方法。详细实现一系列产品对象的创建
    • Abstract Product:定义一类产品对象的接口
    • Concrete Product:详细的产品实现对象。通常在详细工厂里面,会选择详细的产品实现对象,来创建符合抽象工厂定义的方法返回的产品类型的对象
    • Client:client,主要使用抽象工厂来获取一系列所须要的产品对象,然后面向这些产品对象的接口编程,以实现须要的功能。

    抽象工厂接口

    public interface AbstractFactory {
        public AbstractProductA createProductA();
        public AbstractProductB createProductB();
    }
    

    抽象产品A的接口

    public interface AbstractProductA {
    
    }
    

    抽象产品B的接口

    public interface AbstractProductB {
    
    }
    

    产品A详细实现

    public class ProductA1 implements AbstractProductA {
    }
    
    public class ProductA2 implements AbstractProductA {
    }
    

    产品B详细实现

    public class ProductB1 implements AbstractProductB {
    }
    
    public class ProductB2 implements AbstractProductB {
    }
    

    详细工厂实现

    public class ConcreteFactory1 implements AbstractFactory {
        public AbstractProductA createProductA() {
            return new ProductA1();
        }
    
        public AbstractProductB createProductB() {
            return new ProductB1();
        }
    }
    
    public class ConcreteFactory2 implements AbstractFactory {
        public AbstractProductA createProductA() {
            return new ProductA2();
        }
    
        public AbstractProductB createProductB() {
            return new ProductB2();
        }
    }
    

    client

    public class Client {
        public static void main(String[] args) {
            AbstractFactory af = new ConcreteFactory1();
            af.createProductA();
            af.createProductB();
        }
    }
    

    实际应用场景

    • 电脑组装,有不同厂家的cpu和不同厂家的主板等一系列产品。


    DAO(Data Access Object)数据訪问对象

    • 数据源不同,比如:数据库数据源、LDAP数据源;本地数据源,远程数据源。

    • 存储类型不同,关系型数据库、面向对象数据库、纯文件、XML
    • 訪问方式的不同。JDBC、JPA、EntityBean、Hibernate、iBatis
    • 供应商不同,oracel,mysql
    • 版本号不同

    DAO抽象和封装全部对数据的訪问。

    • 底层存储方式固定能够用工厂方法
    • 底层存储方式不固定能够用抽象工厂模式

    工厂方法Factory Methon

    定义

    定义一个用于创建对象的接口。让子类决定实例化哪一个类。Factory Method使用一个类的实例化延迟到其子类。

    本质

    延迟到子类来选择实现

    长处

    • 让父类不知道详细实现的情况下,完毕自身的功能调用;而详细的实现延迟到子类来实现
    • 更easy扩展对象的新版本号。工厂方法给子类提供一个挂钩。使得扩展的对象版本号变得非常easy
    • 连接平行的类层次

    缺点

    • 详细产品对象和工厂方法的耦合性

    演示样例


    • Product:定义工厂方法所创建的对象的接口,也就是实际须要使用的对象的接口。

    • ConcreteProduct:详细的Product接口的实现对象
    • Creator:创建器。声明工厂方法,工厂方法一般会返回一个Product类型的实例对象,并且多是抽象方法。也能够在Creator里面提供工厂方法的默认实现,让工厂方法返回一个缺省的Product类型的实例对象。
    • ConcreteCreator:详细的创建器对象。覆盖实现Creator定义的工厂方法,返回详细的Product实例。

    Product

    public interface Product {
        // 定义Product的属性和方法
    }
    

    ConcreteProduct

    public class ConcreteProduct implements Product {
        // 实现Product要求的方法
    }
    

    创建器

    public abstract class Creator {
    
        // 创建Product的工厂方法,一般不正确外
        protected abstract Product factoryMethod();
    
        // 提供给外部使用的方法
        public void someOperation() {
            Product product = factoryMethod();
        }
    }
    

    创建器详细实现

    public class ConcreteCreator extends Creator {
        protected Product factoryMethod() {
            return new ConcreteProduct();
        }
    }
    

    实际应用场景

    • 实现一个导出数据的应用框架。来让客户选择数据的导出方式,并真正运行数据导出。

      各分公司在局域网独立运行自己的服务,每天业务结束将数据导出成某种格式,传送给总部,总部导入数据,核算。

    • 假设一个类须要创建某个接口的对象,可是又不知道详细的实现。这样的情况能够选用工厂方法模式。把创建对象的工作延迟到子类中去实现
    • 假设一个类本身就希望由它的子类来创建所需的对象的时候

    IoC/DI

    Q&A

    • 參与者都有谁?
      • 某个对象:随意的。普通的Java对象
      • Ioc/DI容器:框架程序
      • 某个对象的外部资源:对象须要的,可是从对象外部获取的,都统称为资源,比方对象须要的其它对象,或者是对象须要的文件资源等
    • 依赖:谁依赖于谁?为什么须要依赖?
      • 某个对象依赖于IoC/DI容器
      • 对象须要IoC/DI的容器来提供对象须要的外部资源
    • 注入:谁注入于谁?究竟注入什么?
      • Ioc/DI容器注入某个对象
      • 注入某个对象所须要的外部资源
    • 控制反转:谁控制谁?控制什么?为何叫反转(有反转就应该有正转了)?
      • IoC/DI容器来控制对象
      • 主要控制对象实例的创建
      • 反转是相对正向而言的。假设A里面使用了C,当然会直接去创建C的对象。也就是说A主动去获取外部资源C,这叫正向。反向就是A不再主动去获取外部资源C,而是被动等待,等待Ioc/DI容器获取一个C的实例,然后反向注入到A类中。
    • 依赖注入和控制反转是同一概念吗?
      • 依赖注入和控制反转是对同一件事的不同描写叙述。依赖注入(应用程序角度):应用程序依赖容器创建并注入它所须要的外部资源。控制反转(容器角度):容器控制应用程序,由容器反向地向应用程序注入其所须要的外部资源。

    简单工厂Simple Factory

    定义

    提供一个创建对象实例的功能。而无须关心其详细实现。被创建实例的类型能够是接口,抽象类也能够是详细类。

    本质

    选择实现

    长处

    • 帮助封装。让组件外部能真正面向接口编程
    • 解耦,通过简单工厂,实现client和详细实现类解耦

    缺点

    • 使用时,必须对配置非常熟悉
    • 静态方法创建接口,不方便扩展子工厂(通常也不须要扩展。所以不算一个严重的缺点)

    演示样例

    • Api:定义客户所须要的功能接口
    • Impl:详细实现Api的实现类。可能会有多个
    • Factory:工厂,选择合适的实现类来创建Api接口对象
    • Client:client,通过Factory来获取Api接口对象,然后面向Api接口编程

    API定义

    /**
     * 接口定义
     * /
    public interface Api {
        public void operation(String s);
    }
    

    实现A

    /**
     * 接口的详细实现A
     * /
    public class ImplA implements Api {
        public void operation(String s) {
            System.out.println("ImplA s==" + s);
        }
    }
    

    实现B

    /**
     * 接口的详细实现B
     * /
    public class ImplB implements Api {
        public void operation(String s) {
            System.out.println("ImplB s==" + s);
        }
    }
    

    工厂类

    public class Factory {
        public static Api createApi(int condition) {
            Api api = null;
            if(condition == 1) {
                api = new ImplA();
            } else if(condition == 2) {
                api = new ImplB();
            }
            return api;
        }
    }
    

    配置版工厂类(反射,可考虑用NIO优化)

    public class FactoryTest {
    
        public static Api createApi() {
            Properties p = new Properties();
            InputStream in = null;
            try {
                in = FactoryTest.class.getResourceAsStream("FactoryTest.properties");
                p.load(in);
            } catch (IOException e) {
                System.out.println("");
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            Api api = null;
            try {
                api = (Api) Class.forName(p.getProperty("implClass")).newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return api;
        }
    }
    

    client

    public class Client {
        public static void main(String [] args) {
            Api api = Factory.createApi(1);
            api.operation("正在使用简单工厂");
        }
    }
    

    配置版client

    public class Client {
        public static void main(String [] args) {
            Api api = Factory.createApi();
            api.operation("正在使用简单工厂");
        }
    }
    

    实际应用场景

    • 假设想要全然封装隔离详细实现。让外部仅仅能通过接口来操作封装体
    • 假设想要把创建对象的职责集中管理和控制

    建造模式Builder

    定义

    将一个复杂的构建与它的表示分离。使得相同的构建过程能够创建不同的表示。

    本质

    分离总体构建算法和部件构造

    长处

    • 松散耦合
    • 能够非常easy地改变产品的内部表示。

    • 更好的复用性。非常好的实现了构建算法和详细产品实现的分离。

    缺点

    未总结

    演示样例

    • Builder:生成器接口。定义创建一个Product对象所需的各个部件的操作。

    • ConcreteBuilder:详细的生成器实现,实现各个部件的创建。并负责组装Product对象的各个部件。同一时候还提供一个让用户获取组装完毕后的产品对象的方法
    • Director:指导者。主要用来使用Builder接口。以一个统一的过程来构建所须要的Product对象
    • Product:产品,表示被生成器构建的复杂对象,包括多个部件

    生成器接口

    public interface Builder {
        public void buildPart();
    }
    

    详细生成器的实现

    public class ConcreteBuilder implements Builder {
        // 生成器终于构建的产品对象
        private Product resultProduct;
    
        // 获取终于构建的产品对象
        public Product getResult() {
        }s
    
        public void buildPart() {
            // 构建某个部件
        }
    }
    

    对应的产品对象接口

    public interface Product {
    
    }
    

    指导者

    public class Director {
        // 持有当前须要使用的生成器对象
        private Builder builder;
    
        public Director(Builder builder) {
            this.builder = builder;
        }
    
        // 指导生成器构建终于的产品对象
        public void construct() {
            // 通过使用生成器接口来构建终于的产品对象
            builder.buildPart();
        }
    }
    

    实际应用场景

    • 一部分是部件构造和产品装配,还有一部分是总体构建的算法
    • 假设创建对象的算法,应该独立于该对象的组成部分以及它们的装配方式时
    • 假设同一个构建过程有着不同的表示时

    原型模式Prototype

    定义

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象

    本质

    长处

    缺点

    演示样例

    • Prototype:声明一个克隆自身的接口。用来约束想要克隆自己的类,要求它们都要实现这里定义的克隆方法。
    • ConcretePrototype:实现Prototype接口的类,这些类真正实现了克隆自身的功能。

    • Client:使用原型client,首先要获取到原型实例对象,然后通过原型实例克隆自身来创建新的对象实例

    原型接口

    public interface Prototype {
        public Prototype clone();
    }
    

    克隆详细实现

    public class ConcretePrototype1 implements Prototype {
        private String field1;
    
        private Product product1;
    
        public String getProduct1() {
            return this.product1;
        }
        pubilc void setProduct1(String product1) {
            this.product1 = product1;
        }
    
        public String getField1() {
            return this.field1;
        }
        pubilc void setField1(String field1) {
            this.field1 = field1;
        }
    
        public Prototype clone() {
            Prototype prototype = new ConcretePrototype1();
            prototype.setField1(this.field1);
            prototype.setProduct1((Product) this.product1.cloneProduct());
            return prototype;
        }
    }
    
    public class ConcretePrototype2 implements Prototype {
        private String field2;
    
        private Product product2;
    
        public String getProduct2() {
            return this.product2;
        }
        pubilc void setProduct2(String product2) {
            this.product2 = product2;
        }
    
        public String getField2() {
            return this.field2;
        }
        pubilc void setField2(String field2) {
            this.field2 = field2;
        }
    
        public Prototype clone() {
            Prototype prototype = new ConcretePrototype2();
            prototype.setField1(this.field2);
            prototype.setProduct2((Product) this.product2.cloneProduct());
            return prototype;
        }
    }
    

    原型管理器

    public class PrototypeManager {
        private static Map<String, Prototype> map = new HashMap<String, Prototype>();
    
        private PrototypeManager() {
        }
    
        public synchronized static void setPrototype(String prototypeId, Prototype prototype) {
            map.put(prototypeId, prototype);
        }
    
        public synchronized static void removePrototype(String prototypeId) {
            map.remove(prototypeId);
        }
    
        public synchronized static Prototype getPrototype(String prototypeId) throws Exception {
            Prototype prototype = map.get(prototypeId);
            if(prototype == null) {
                throw new Exception("您希望获取的原型还没有注冊或已被销毁");
            }
            return prototype;
        }
    }
    

    client

    public class Client {
        private Prototype prototype;
        public Client(Prototype prototype) {
            this.prototype = prototype;
        }
        public void operation() {
            Prototype newPrototype = prototype.clone();
        }
    }
    

    实际应用场景

    观察者模式Observer

    定义

    对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,全部依赖它的对象都得到通知并被自己主动更新。

    本质

    触发联动

    长处

    • 观察者模式实现了观察者和目标之间的抽象耦合
    • 观察者模式实现了动态联动
    • 观察者模式支持广播通信

    缺点

    • 可能会引起无谓的操作

    演示样例

    • Subject:目标对象,通常具有例如以下功能
      • 一个目标能够被多个观察者观察
      • 目标提供对观察者注冊和退订的维护
      • 当目标的状态发生变化时,目标负责通知全部注冊的,有效的观察者
    • Observer:定义观察者的接口。提供目标通知时对应的更新方法,这个更新方法进行对应的业务处理,能够在这种方法里面回调目标对象,以获取目标对象的数据
    • ConcreteSubject:详细的目标实现对象,用来维护目标状态,当目标对象的状态发生变化,通知全部注冊的。有效的观察者,让观察者运行对应的处理。

    • ConcreteObserver:观察者的详细实现对象。用来接收目标的通知,并进行对应的兴许处理,比方更新自身的状态以保持和目标的对应状态一致。

    目标对象

    public class Subject {
        private List<Observer> observers = new ArrayList<Observer>();
    
        // 注冊观察者对象
        public void attach(Observer observer) {
            observers.add(observer);
        }
    
        // 删除观察者对象
        public void detach(Observer observer) {
            observers.remove(observer);
        }
    
        // 通知全部注冊的观察者对象
        protected void notifyObservers() {
            for(Observer observer: observers) {
                observer.update(this);
            }
        }
    }
    

    详细的目标对象

    public class ConcreteSubject extends Subject {
        private String subjectState;
    
        public String getSubjectState() {
            return subjectState;
        }
    
        public void setSubjectState(String sunjectState) {
            this.subjectState = subjectState;
            this.notifyObservers();
        }
    }
    

    观察者接口

    public interface Observer {
        public void update(Subject subject);
    }
    

    详细观察者

    public class ConcreteObserver implements Observer {
        private String observerState;
    
        public void update(Subject subject) {
            observerState = ((ConcreteSubject) subject).getSubjectState();
        }
    }
    

    client

    public class Client {
        public static void main(String[] args) {
            NewsPaper subject = new NewsPaper();
            Reader reader1 = new Reader();
            reader1.setName("张三");
    
            Reader reader2 = new Reader();
            reader2.setName("李四");
    
            Reader reader3 = new Reader();
            reader3.setName("李四");
    
            subject.attach(reader1);
            subject.attach(reader2);
            subject.attach(reader3);
    
            subject.setContent("本期内容是观察者模式");
        }
    }
    

    实际应用场景

    • 推模式:目标对象主动向观察者推送目标的详细信息。无论观察者是否须要,推送的消息一般是目标对象的全部或部分数据,相当于是在广播通信。

      适用于目标对象知道观察者须要什么数据。

    • 拉模式:目标对象在通知观察者的时候。仅仅传递少量信息。

      假设观察者须要详细的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据。这样在观察者须要获取数据的时候,就能够通过这个引用来获取了。适用于目标对象不知道观察者须要什么数据,将自己的引用传给观察者,让观察者按需取值。这个更加通用。

    策略模式Strategy

    定义

    定义一系列的算法。把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。

    本质

    分离算法,选择实现

    长处

    • 定义一系列算法
    • 避免多重条件语句
    • 更好的扩展性

    缺点

    • 客户必须了解每种策略的不同
    • 添加了对象数目
    • 仅仅合适扁平的算法结构

    演示样例

    • Strategy:策略接口,用来约束一系列详细的策略算法。Context使用这个接口来调用详细的策略实现定义的算法
    • ConcreteStrategy:详细的策略实现,也就是详细的算法实现
    • Context:上下文,负责和详细的策略类交互。

      通常上下文会持有一个真正的策略实现,上下文还能够让详细的策略类来获取上下文的数据,甚至让详细的策略类来回调上下文的方法。

    策略接口

    public interface Strategy {
        public void algorithmInterface();
    }
    

    详细策略

    public interface ConcreteStrategyA implements Strategy {
        public void algorithmInterface() {
        }
    }
    
    public interface ConcreteStrategyB implements Strategy {
        public void algorithmInterface() {
        }
    }
    

    上下文

    public class Context {
        private Strategy strategy;
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
        public void contextInterface() {
            strategy.algorithmInterface();
        }
    }
    

    实际应用场景

    责任链模式China of Responsibility

    定义

    使用多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。

    将这些对象连成一条链,并沿着这条链传递该请求,直到一个对象处理它为止。

    本质

    分离职责。动态组合

    长处

    • 请求者和接收者松散耦合
    • 动态组合职责

    缺点

    • 产生非常多细粒度对象
    • 不一定能被处理。

      传递完都没被处理,须要提供默认的处理。

    演示样例

    • Handler:定义职责的接口
    • ConcreteHandler:实现职责的类。在这个类中,实现对在它职责范围内请求的处理。假设不处理,就继续转发请求给后继者。

    • Client:职责链client

    职责的接口

    public abstract class Handler {
        protected Handler successor;
        public void setSuccessor(Handler successor) {
            this.successor = successor;
        }
    
        public abstract void handleRequest();
    }
    

    通用的请求对象

    public class RequestModel {
        private String type;
        public RequestModel(String type) {
            this.type = type;
        }
    
        public String getType() {
            return type;
        }
    }
    

    详细的请求对象

    public class ConcreteRequestModel extends RequestModel {
        public final static String A_TYPE = "A";
        public ConcreteRequestModel() {
            super(A_TYPE);
        }
        private String field1;
        ...
    }
    

    详细的职责对象

    public class ConcreteHandler1 extends Handler {
        public Object handleRequest(RequestModel rm) {
            // 依据某些条件推断是否属于自己处理的职责范围
            boolean someCondition = false;
            Object result;
            if(someCondition) {
                // 处理
                return result;
            } else {
                // 不处理,转发请求给后继职责对象
                if(this.successor != null) {
                    return this.successor.handleRequest(rm);
                } else {
                    return result;
                }
            }
        }
    }
    

    client(可採用链表改进client)

    public class Client {
        public static void main(String[] args) {
            Handler h1 = new ConcreteHandler1();
            Handler h2 = new ConcreteHandler2();
            h1.setSuccessor(h2);
            h1.handleRequest();
        }
    }
    

    实际应用场景

    • 权限检查
    • 通用数据校验
    • 数据逻辑校验
    • 过滤器
    • 能够和组合模式一起使用。通过组合模式将责任组合起来

    中介者模式Mediator

    定义

    本质

    封装隔离

    长处

    • 松散耦合
    • 集中控制交互
    • 多对多变成一对多

    缺点

    • 过度集中化。中介者对象十分复杂。难于管理和维护。

    演示样例

    • Mediator:中介者接口,在里面定义各个同事之间交互须要的方法,能够是公共的通信方法。比方changed方法。大家都用。也能够是小范围的交互方法。
    • ConcreteMediator:详细中介者实现对象。它须要了解并维护各个同事对象,并负责详细的协调各同事对象的交互关系。
    • Colleague:同事类的定义,通常实现成抽象类,主要负责约束同事对象的类型,并实现一些详细同事类之间的公共功能。
    • ConcreteColleague:详细的同事类,实现自己的业务,在须要与其它同事通信的时候。就与持有的中介者通信,中介者会负责与其它的同事交互。

    同事类的抽象父类

    public abstract class Colleague {
    
        private Mediator mediator;
    
        public Colleague(Mediator mediator) {
            this.mediator = mediator;
        }
    
        public Mediator getMediator() {
            return mediator;
        }
    }
    

    同事类A

    public class ConcreteColleagueA extends Colleague {
        public ConcreteColleagueA(Mediator mediator) {
            super(mediator);
        }
    
        public void someOperation() {
            // 须要跟其它同事通信的时候。通知中介者对象
            getMediator().changed(this);
        }
    }
    

    同事类B

    public class ConcreteColleagueB extends Colleague {
        public ConcreteColleagueB(Mediator mediator) {
            super(mediator);
        }
    
        public void someOperation() {
            // 须要跟其它同事通信的时候,通知中介者对象
            getMediator().changed(this);
        }
    }
    

    中介者接口
    public interface Mediator {

        public void changed(Colleague colleague);
    }
    

    中介者实现

    public class ConcreateMediator implements Mediator {
        private ConcreteColleagueA colleagueA;
    
        private ConcreteColleagueB colleagueB;
    
        public void setConcreteColleagueA(ConcreteColleagueA colleague) {
            colleagueA = colleague;
        }
    
        public void setConcreteColleagueB(ConcreteColleagueB colleague) {
            colleagueB = colleague;
        }
    
        public void changed(Colleague colleague) {
            // 某个同事类发生了变化,通常须要与其它同事交互
            // 详细协调对应的同事对象来实现协作行为
        }
    }
    

    client

    public class Client {
    
    }
    

    实际应用场景

    • 假设一组对象之间的通信方式比較复杂,导致相互依赖。结构混乱,能够採用中介者模式
    • 假设一个对象引用非常多的对象,并直接跟这些对象交互。导致难以复用该对象

    外观模式Facade

    定义

    为子系统中的一组接口提供一个一致的界面。也就是一个高层接口。

    本质

    为多模块提供统一接口。封装交互,简化调用

    长处

    • 降低外部与子系统内多模块的交互,松散耦合
    • 出现变化时,仅仅需改动Facade的实现就好,仅仅需改这一个地方,由于非常多client都会用这个外观模式,无需改动全部的client。从而达到一改全改。
    • 调用多个模块在外观模式调用一次就好了,无需全部client都调用一次,降低反复调用
    • client无需了解系统的内部实现,无需了解每一个模块的细节,也不须要去和多个模块交互,节省了学习成本。

    • 将外部接口和外部接口分开。封装更好

    缺点

    • 过多或者不合理的Facadeeasy让人迷惑,究竟是调用Facade好。还是直接调用模块好。

    演示样例


    A模块Api

    public interface AModuleApi {
        public void testA1(); //系统外部使用
        public void testA2(); //系统内部使用
        public void testA3(); //系统内部使用
    }
    

    实现A模块

    public class AModuleImpl implements AModuleApi {
        public void testA1() {
            System.out.println("如今在A模块里面操作testA1方法");
        }
        public void testA2() {
            System.out.println("如今在A模块里面操作testA2方法");
        }
        public void testA3() {
            System.out.println("如今在A模块里面操作testA3方法");
        }
    }
    

    B模块Api

    public interface BModuleApi {
        public void testB1(); //系统外部使用
        public void testB2(); //系统内部使用
        public void testB3(); //系统内部使用
    }
    

    实现B模块

    public class BModuleImpl implements BModuleApi {
        public void testB1() {
            System.out.println("如今在B模块里面操作testB1方法");
        }
        public void testB2() {
            System.out.println("如今在B模块里面操作testB2方法");
        }
        public void testB3() {
            System.out.println("如今在B模块里面操作testB3方法");
        }
    }
    

    C模块Api

    public interface CModuleApi {
        public void testC1(); //系统外部使用
        public void testC2(); //系统内部使用
        public void testC3(); //系统内部使用
    }
    

    实现B模块

    public class CModuleImpl implements CModuleApi {
        public void testC1() {
            System.out.println("如今在C模块里面操作testC1方法");
        }
        public void testC2() {
            System.out.println("如今在C模块里面操作testC2方法");
        }
        public void testC3() {
            System.out.println("如今在C模块里面操作testC3方法");
        }
    }
    

    外观接口

    public interface FacadeApi {
        // 仅仅暴露对外部调用的接口
        public void testA1();
        public void testB1();
        public void testC1();
        public void test();
    }
    

    外观类

    public class Facade {
        public void test() {
            AModuleApi a = new AModuleImpl();
            a.testA1();
            BModuleApi b = new BModuleApi()。
            b.testB1();
            CModuleApi c = new CModuleImpl();
            c.testC1();
        }
    }
    

    client

    public class Client {
        public static void main(String [] args) {
            Facade facade = new Facade();
            facade.test();
        }
    }
    

    实际应用场景

    代理模式Proxy

    定义

    为其它对象提供一种代理以控制对这个对象的訪问。

    本质

    控制对象訪问

    长处

    缺点

    演示样例

    • Proxy:代理对象。

      实现与详细的目标对象一样的接口,这样就能够使用代理来取代详细的目标对象。保存一个指向详细目标对象的引用,能够在须要的时候调用详细的目标对象。能够控制对详细目标对象的訪问。并能够负责创建和删除它。

    • Subject:目标接口,定义代理和详细目标对象的接口,这样就能够在不论什么使用详细目标对象的地方使用代理对象。
    • RealSubject:详细的目标对象。真正实现目标接口要求的功能。

    抽象的目标接口

    public interface Subject {
        public void request();
    }
    

    详细的目标对象。是真正被代理的对象

    public class RealSubject implements Subject {
        public void request() {
        }
    }
    

    代理对象的实现示意

    public class Proxy implements Subject {
        private RealSubject realSubject = null;
        public Proxy(RealSubject realSubject) {
            this.realSubject = realSubject;
        }
        public void request() {
            // 在转调详细的目标对象前。能够运行一些功能处理
    
            // 转调详细的目标对象的方法
            realSubject.requst();
    
            // 在转调详细的目标对象后,能够运行一些功能处理
        }
    }
    

    实际应用场景

    • 一次性訪问多条数据。当选择一个部门或者分公司时。要把这个部门或者分公司下的全部员工都显示出来,并且不要翻页。方便进行业务处理。


    定义用户数据对象

    public interface UserModelApi {
    
        public String getUserId();
        public void setUserId(String userId);
        public String getName();
        public void setName(String name);
        public String getDepId();
        public void setDepId(String depId);
        public void String getSex();
        public void setSex(String sex);
    }
    

    代理类

    public class Proxy implements UserModelApi {
        private UserModel realSubject = null;
        public Proxy(UserModel realSubject){
            this.realSubject = realSubject;
        }
    
        // 标识是否已经又一次装载过数据
        private boolean loaded = false;
        public String getUserId() {
            return realSubject.getUserId();
        }
    
        public void setUserId(String userId) {
            realSubject.setUserId(userId);
        }
    
        public String getName() {
            return realSubject.getName();
        }
    
        public void setName(String name) {
            realSubject.setName(name);
        }
    
        public void setDepId(String depId) {
            realSubject.setDepId(depId);
        }
    
        public void setSex(String sex) {
            realSubject.setSex(sex);
        }
    
        public String getDepId() {
            // 须要判读是否已经装载过了
            if(!this.loaded) {
                reload();
                // 设置又一次装载的标志为true
                this.loaded = true;
            }
            return realSubject.getDepId();
        }
    
        public String getSex() {
            // 须要判读是否已经装载过了
            if(!this.loaded) {
                reload();
                // 设置又一次装载的标志为true
                this.loaded = true;
            }
            return realSubject.getSex();
        }
    
        private void reload() {
            Connection conn = null;
            try {
                conn = this.getConnection();
                String sql = "select * from tbl_user where userId = ?";
                PreparedStatement pstmt = conn.prepareStatement(sql);
                pstmt.setString(1, realSubject.getUserId());
                if(re.next()) {
                    realSubject.setDepId(rs.getString("depId"));
                    realSubject.setSex(rs.getString("sex"));
                }
                rs.close();
                pstmt.close();
            } catch (Exception err) {
                err.printStackTrace();
            } finally {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    • 动态代理AOP

    代理分类

    • 虚代理:依据须要来创建开销非常大的对象,该对象仅仅有在须要的时候才会被真正创建
    • 远程代理:用来在不同的地址空间上代表同一个对象,这个不同的地址空间能够是在本机,也能够在其它机器上。在Java里面最典型的就是RMI技术
    • copy-on-write代理:在client操作的时候,仅仅有对象确实改变了,才会真的拷贝或者克隆一个目标对象,算是虚代理的一个分支
    • 保护代理:控制对原始对象的訪问,假设有须要,能够给不同的用户提供不同的訪问权限。以控制他们对原始对象的訪问。
    • Cache代理:为那些昂贵操作的结果提供暂时的存储空间,以便多个client能够共享这些结果
    • 防火墙代理:保护对象不被恶意用户訪问和操作。

    • 同步代理:使多个用户能够同一时候訪问,目标对象而没有冲突。
    • 智能指引:在訪问对象时运行一些附加操作,比方。对指向实际对象的引用计数、第一次引用一个持久对象时。将它装入内存等。

    适配器模式Adapter

    定义

    把不兼容的接口转换匹配成客户须要的接口。复用已有的功能

    本质

    转换匹配,复用功能。

    长处

    • 兼容老接口,更好的复用。

    • 更好的扩展

    缺点

    • 过多使用适配器。会让系统非常零乱。不easy总体进行把握。

    演示样例


    • Client:client,调用自己须要的领域接口Target
    • Traget:定义client须要的跟特定领域相关的接口
    • Adaptee:已经存在的接口,通常能满足client的功能要求。可是接口与client要求的特定领域接口不一致,须要被适配
    • Adapter:适配器,把Adaptee适配成为Client须要的Target

    Target Api

    public interface Target {
        public void request();
    }
    

    被适配的类

    public class Adaptee {
        public void specificRequest() {
            //详细功能
        }
    }
    

    适配器

    public class Adapter implements Target {
        private Adaptee adaptee;
        public Adapter(Adaptee adaptee) {
            this.adaptee = adaptee;
        }
        public void request() {
        }
    }
    

    client

    public class Client {
        public static void main(String [] args) {
            Adaptee adaptee = new Adaptee();
            Target target = new Adapter(adaptee);
            target.request();
        }
    }
    

    实际应用场景

    • 假设想要使用一个已经存在的类。可是它的接口不符合你的需求
    • 假设想创建一个能够复用的类,这个类可能和一些不兼容的类一起工作
    • 假设想使用一些已经存在的子类,可是不可能对每一个子类都进行适配。这样的情况能够选用对象适配器,直接适配这些子类的父类就能够了

    装饰模式Decrator

    定义

    动态地给一个对象加入一些额外的职责。就添加功能来说,装饰模式比生成子类更为灵活。

    本质

    动态组合

    长处

    • 比继承更灵活。继承是静态的。装饰器採用把功能分离到每一个装饰器中,通过对象组合动态使用。
    • 更easy复用功能。
    • 简化高层定义。

    缺点

    • 会产生非常多细粒度的对象

    演示样例

    • Component:组件对象的接口。能够给这些对象动态地加入职责
    • ConcreteComponent:详细的组件对象,实现组件对象接口,通常就是被装饰器装饰的原始对象,也就是能够给这个对象加入职责。
    • Decorator:全部装饰器的抽象父类,须要定义一个与组件接口一致的接口,并持有一个Component对象,事实上就是持有一个被装饰的对象。

    • ConcreteDecorator:实际的装饰器对象,实现详细要向被装饰对象加入的功能

    组件对象的接口

    public abstract class Component {
        public abstract void operation();
    }
    

    详细实现组件对象

    public class ConcreteComponent extends Component {
        public void operation() {
        }
    }
    

    装饰器的抽象父类

    public abstract class Decorator extends Component {
        protected Component component;
        public Decorator(Component component) {
            this.component = component;
        }
    
        public void operation() {
            // 转发请求给组件对象,能够在转发前后运行一些附加动作
            component.operation();
        }
    }
    

    装饰器的详细实现A

    public class ConcreteDecoratorA extends Decorator {
        public ConcreteDecoratorA(Component component) {
            super(component);
        }
    
        // 加入的状态
        private String addedState;
        public String getAddedState() {
            return addedState;
        }
    
        public void setAddedState(String addedState) {
            this.addedState = addedState;
        }
    
        public void operation() {
            // 调用父类的方法,能够在调用前后运行一些附加动作
            super.operation();
            // ...
            String useAddedState = addedState;
        }
    }
    

    装饰器的详细实现B

    public class ConcreteDecoratorB extends Decorator {
        public ConcreteDecoratorB(Component component) {
            super(component);
        }
    
        // 加入的职责
        private void addedBehavior() {
            // 须要加入的职责实现
        }
    
        public void operation() {
            // 调用父类的方法。能够在调用前后运行一些附加动作
            super.operation();
            // ...
            addedBehavior();
        }
    }
    

    实际应用场景

    • 灵活的奖金计算
    • I/O流
  • 相关阅读:
    android 获取字体宽高
    android 渐变
    android 拖动按钮
    android 模拟器使用
    android 启动其它apk
    How to solve Error: This attribute must be localized. 两种方式
    Chirp用音频 传输文件
    android 打开指定网页
    防止apk被反编译
    iphone 滑块制作
  • 原文地址:https://www.cnblogs.com/llguanli/p/8793669.html
Copyright © 2011-2022 走看看