码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式

时间:2018-04-11 10:44:05      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:except   post   reader   iba   sele   https   lda   统一   复杂   

更新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流

设计模式

标签:except   post   reader   iba   sele   https   lda   统一   复杂   

原文地址:https://www.cnblogs.com/llguanli/p/8793669.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!