美文网首页
设计模式

设计模式

作者: 西海岸虎皮猫大人 | 来源:发表于2020-10-20 16:52 被阅读0次

0 概述

创建型模式:
单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
结构型模式:
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式:
模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式、职责链模式、访问者模式

1 单例模式

五种实现方式

1.饿汉式
/**
 * 单例模式-饿汉式
 * 类初始化时,立即加载这个对象,线程安全
 */
public class EagerSingleton {
    private static EagerSingleton instance = new EagerSingleton();

    /**
     * 私有化构造器
     */
    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }
}
2.懒汉式
/**
 * 单例模式-懒汉式
 * 使用时再创建实例,为保证线程安全需要方法同步,效率低
 */
public class LazySingleton {
    private static LazySingleton instance;

    private LazySingleton() {}

    public static synchronized LazySingleton getInstance() {
        if(instance == null) {
            instance =  new LazySingleton();
        }
        return instance;
    }
}
3.双重检查锁
/**
 * 单例模式-双重检查锁
 * 由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用
 */
public class DoubleCheckSingleton {
    private static DoubleCheckSingleton instance;

    public static DoubleCheckSingleton getInstance() {
        if(instance == null) {
            DoubleCheckSingleton dc;
            synchronized (DoubleCheckSingleton.class) {
                dc = instance;
                if(dc == null) {
                    synchronized (DoubleCheckSingleton.class) {
                        if(dc == null) {
                            dc = new DoubleCheckSingleton();
                        }
                    }
                    instance = dc;
                }
            }
        }
        return instance;
    }
}
4.静态内部类
/**
 * 单例模式-静态内部类
 * 线程安全\延时加载且调用效率高
 */
public class StaticInnerSingleton {
    private static class StaticInnerSingletonInstance {
        private static final StaticInnerSingleton instance = new StaticInnerSingleton();
    }

    private StaticInnerSingleton() {}

    public static StaticInnerSingleton getInstance() {
        return StaticInnerSingletonInstance.instance;
    }
}
5.枚举
/**
 * 单例模式-枚举
 */
public enum EnumSingleton {
    INSTANCE;
}

单例模式测试

1.测试
/**
 * 测试五种方式实现单例
 */
public class Client1 {
    public static void main(String[] args) {
        EagerSingleton e1 = EagerSingleton.getInstance();
        EagerSingleton e2 = EagerSingleton.getInstance();
        System.out.println(e1 == e2);

        LazySingleton l1 = LazySingleton.getInstance();
        LazySingleton l2 = LazySingleton.getInstance();
        System.out.println(l1 == l2);

        DoubleCheckSingleton d1 = DoubleCheckSingleton.getInstance();
        DoubleCheckSingleton d2 = DoubleCheckSingleton.getInstance();
        System.out.println(d1 == d2);

        StaticInnerSingleton s1 = StaticInnerSingleton.getInstance();
        StaticInnerSingleton s2 = StaticInnerSingleton.getInstance();
        System.out.println(s1 == s2);

        EnumSingleton en1 = EnumSingleton.INSTANCE;
        EnumSingleton en2 = EnumSingleton.INSTANCE;
        System.out.println(en1 == en2);
    }
}
2.测试效率
/**
 * 测试单例五种方式效率
 */
public class Client2 {
    public static void main(String[] args) throws InterruptedException {
        Long start = System.currentTimeMillis();
        int threadNum = 10;
        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);
        for(int i=0;i<threadNum;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {

                    for(int i=0;i<1000000;i++){
//                        Object o = EagerSingleton.getInstance(); // 耗时52ms
//                        Object o = LazySingleton.getInstance(); // 耗时342ms
//                        Object o = DoubleCheckSingleton.getInstance(); // 耗时55ms
//                        Object o = StaticInnerSingleton.getInstance(); // 耗时54ms
//                        Object o = EnumSingleton.INSTANCE; // 耗时46ms
                    }
                    countDownLatch.countDown();
                }
            }).start();
        }
        countDownLatch.await();
        long end = System.currentTimeMillis();
        System.out.println("总耗时:"+(end-start));
    }
}
3.测试破解
/**
 * 通过反射和反序列化方式破解单例
 */
public class Client3 {
    public static void main(String[] args) throws Exception {
        //通过反射方式构造多个对象
        Class<EagerSingletonHack> clazz = (Class<EagerSingletonHack> )Class.forName("cn.dfun.pattern.singleton.EagerSingletonHack");
        Constructor<EagerSingletonHack> c = clazz.getDeclaredConstructor();
        // 构造器设为可见
        c.setAccessible(true);
        EagerSingletonHack e1 = c.newInstance();
        EagerSingletonHack e2 = c.newInstance();
        System.out.println(e1 == e2);

        //通过反序列化的方式构造多个对象
        EagerSingletonHack e3 = EagerSingletonHack.getInstance();
        FileOutputStream fos = new FileOutputStream("d:/a.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(e3);
        oos.close();
        fos.close();
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
        EagerSingletonHack e4 =  (EagerSingletonHack) ois.readObject();
        System.out.println(e3 == e4);
    }
}
防破解
/**
 * 单例模式防破解
 */
public class EagerSingletonHack implements Serializable {
    private static EagerSingletonHack instance = new EagerSingletonHack();

    /**
     * 私有化构造器
     */
    private EagerSingletonHack() {
        // 防止反射方式破解
        if(instance!=null){
            throw new RuntimeException();
        }
    }

    public static EagerSingletonHack getInstance() {
        return instance;
    }

    /**
     * 反序列化时,如果定义了readResolve()则直接返回此方法指定的对象。而不需要单独再创建新对象!
     * @return
     * @throws ObjectStreamException
     */
    private Object readResolve() throws ObjectStreamException {
        return instance;
    }
}

2 工厂模式

使用工厂类创建对象代替new

简单工厂模式

定义Car接口

public interface Car {
    void run();
}

两个具体实现类

public class Audi implements Car{
    @Override
    public void run() {
        System.out.println("Audi run...");
    }
}
public class Benz implements Car{
    @Override
    public void run() {
        System.out.println("Benz run...");
    }
}

工厂类根据类型参数返回具体的实现类

public class CarFactory {
    public static Car createCar(String type) {
        if("Audi".equals(type)) {
            return new Audi();
        } else if("Benz".equals(type)) {
            return new Benz();
        } else {
            return null;
        }
    }
}

客户端只需与工厂类和接口交互

public class Client {
    public static void main(String[] args) {
        Car c1 = CarFactory.createCar("Audi");
        Car c2 = CarFactory.createCar("Benz");
        c1.run();
        c2.run();
    }
}
工厂方法模式

多个不同工厂类实现相同工厂接口
Car接口与实现类与1相同
工厂接口

public interface CarFactory {
    Car createCar();
}

两个工厂实现类

public class AudiFactory implements CarFactory{
    @Override
    public Car createCar() {
        return new Audi();
    }
}
public class BenzFactory implements CarFactory{
    @Override
    public Car createCar() {
        return new Benz();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Car c1 = new AudiFactory().createCar();
        Car c2 = new BenzFactory().createCar();

        c1.run();
        c2.run();
    }
}
抽象工厂模式

生产不同产品族的所有产品
引擎接口及高配低配两个实现类

public interface Engine {
    void run();
}

class LuxuryEngine implements Engine {
    @Override
    public void run() {
        System.out.println("高配引擎");
    }
}

class LowEngine implements Engine {
    @Override
    public void run() {
        System.out.println("低配引擎");
    }
}

座椅接口及低配高配两个实现类

public interface Seat {
    void massage();
}

class LuxurySeat implements Seat {
    @Override
    public void massage() {
        System.out.println("高配座椅");
    }
}

class LowSeat implements Seat {
    @Override
    public void massage() {
        System.out.println("低配座椅");
    }
}

工厂接口及高配低配两个工厂实现类
高配工厂创建高配引擎和座椅
低配工厂创建低配引擎和座椅

public interface CarFactory {
    Seat createSeat();
    Engine createEngine();
}

class LuxuryCarFactory implements CarFactory {
    @Override
    public Seat createSeat() {
        return new LuxurySeat();
    }

    @Override
    public Engine createEngine() {
        return new LuxuryEngine();
    }
}

class LowCarFactory implements CarFactory {
    @Override
    public Seat createSeat() {
        return new LowSeat();
    }

    @Override
    public Engine createEngine() {
        return new LowEngine();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        CarFactory  factory = new LuxuryCarFactory();
        Engine e = factory.createEngine();
        e.run();

        CarFactory  factory2 = new LowCarFactory();
        Seat s = factory2.createSeat();
        s.massage();
    }
}

3 建造者模式

复杂对象子组件构建和装配分离
飞艇类,包含轨道舱\引擎\逃逸塔三个组件

public class Airship {
    //轨道舱
    private OrbitalModule orbitalModule;
    //发动机
    private Engine engine;
    //逃逸塔
    private EscapeTower escapeTower;

    public OrbitalModule getOrbitalModule() {
        return orbitalModule;
    }

    public void setOrbitalModule(OrbitalModule orbitalModule) {
        this.orbitalModule = orbitalModule;
    }

    public Engine getEngine() {
        return engine;
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public EscapeTower getEscapeTower() {
        return escapeTower;
    }

    public void setEscapeTower(EscapeTower escapeTower) {
        this.escapeTower = escapeTower;
    }
}

class OrbitalModule {
    private String name;

    public OrbitalModule(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Engine {
    private String name;

    public Engine(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class EscapeTower {
    private String name;

    public EscapeTower(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

构建器接口

public interface AirshipBuilder {
    Engine builderEngine();
    OrbitalModule builderOrbitalModule();
    EscapeTower  builderEscapeTower();
}

装配器接口

public interface AirshipDirector {
    Airship directAirship();
}

构建器实现类

public class DfunAirshipBuilder implements AirshipBuilder{
    @Override
    public Engine builderEngine() {
        System.out.println("构建dfun发动机!");
        return new Engine("dfun发动机!");
    }

    @Override
    public OrbitalModule builderOrbitalModule() {
        System.out.println("构建dfun轨道舱!");
        return new OrbitalModule("dfun轨道舱!");
    }

    @Override
    public EscapeTower builderEscapeTower() {
        System.out.println("构建dfun逃逸塔!");
        return new EscapeTower("dfun逃逸塔!");
    }
}

装配器实现类

public class DfunAirshipDirector implements AirshipDirector{
    private AirshipBuilder builder;

    public DfunAirshipDirector(AirshipBuilder builder) {
        this.builder = builder;
    }

    @Override
    public Airship directAirship() {
        Engine e = builder.builderEngine();
        OrbitalModule o = builder.builderOrbitalModule();
        EscapeTower et = builder.builderEscapeTower();

        //装配成飞船对象
        Airship ship = new Airship();
        ship.setEngine(e);
        ship.setEscapeTower(et);
        ship.setOrbitalModule(o);

        return ship;
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        AirshipDirector director = new DfunAirshipDirector(new DfunAirshipBuilder());
        Airship ship = director.directAirship();
        System.out.println(ship.getEngine().getName());
    }
}

4 原型模式

原型模式用于拷贝对象,克隆对象属性值与原对象相同
spring bean的创建方式就两种:单例和原型

public class Sheep implements Cloneable, Serializable {
    private String sname;
    private Date birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        // 直接调用Object对象的clone方法实现克隆
        Object obj = super.clone();

        // 深复制
        Sheep s = (Sheep) obj;
        s.birthday = (Date) this.birthday.clone();

        return obj;
    }
    getter/setter/有参无参构造器
}

测试深复制/浅复制

public class Client {
    public static void main(String[] args) throws CloneNotSupportedException {
        Date d = new Date(123123123123L);
        Sheep s1 = new Sheep("多利", d);
        Sheep s2 = (Sheep)s1.clone();
        // 克隆出的对象与原型对象属性值相同
        System.out.println(s2.getSname());
        // 浅克隆,日期为同一对象
        System.out.println(d == s2.getBirthday());
    }
}

使用序列化和反序列化的方式实现深克隆

public class Client2 {
    public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
        Date d = new Date(123123123123L);
        Sheep s1 = new Sheep("多利", d);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(s1);
        byte[] bytes = bos.toByteArray();

        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bis);
        Sheep s2 = (Sheep) ois.readObject();
        // 深复制,日期不同
        System.out.println(d == s2.getBirthday());
    }
}

原型模式效率测试
对象new过程比较耗时,使用原型模型可以显著提升效率

public class Client3 {
    public static void testNew(int size) throws InterruptedException {
        long start = System.currentTimeMillis();
        for (int i = 0; i < size; i++) {
            Laptop t = new Laptop();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    public static void testClone(int size) throws InterruptedException, CloneNotSupportedException {
        long start = System.currentTimeMillis();
        Laptop t = new Laptop();
        for (int i = 0; i < size; i++) {
            Laptop temp = (Laptop) t.clone();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }

    public static void main(String[] args) throws InterruptedException, CloneNotSupportedException {
        testNew(1000);
        testClone(1000);

    }
}

class Laptop implements Cloneable{
    Laptop() throws InterruptedException {
        // 模拟创建对象耗时
        Thread.sleep(10);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

5 适配器模式

场景:USB转换头
将一个类的接口转为客户希望的另一个接口,使原本不兼容的类可以一起工作
被适配的类

public class Adaptee {
    public void request() {
        System.out.println("可以完成客户需要的功能");
    }
 }

接口

public interface Target {
    void handleReq();
}

适配器

/**
 * 适配器
 * 两种关联方式1.继承 2.持有被适配对象引用
 * @author Vincent
 */
public class Adapter implements Target{
    private Adaptee adaptee;

    public Adapter(Adaptee adaptee) {
        this.adaptee = adaptee;
    }

    @Override
    public void handleReq() {
        adaptee.request();
    }
}

客户端

public class Client {
    public void test(Target t) {
        t.handleReq();
    }

    public static void main(String[] args) {
        Client client = new Client();
        Adaptee adaptee = new Adaptee();
        Target t = new Adapter(adaptee);
        client.test(t);
    }
}

场景:
java中流的转换

6 静态代理模式

代理模式:
控制对对象的访问,调用对象方法前做前置处理,调用对象方法后做后置处理
代理模式是AOP的核心
场景:
安全代理,屏蔽真实角色的直接访问
远程代理,通过代理类处理远程方法调用(RMI)
延迟加载,先加载轻量级代理对象,真正需要时再加载真实对象
动态代理:
动态生成代理类
JDK自带动态代理\javaassist字节码操作库\CGLIB\ASM(底层指令维护性差)
接口

public interface Star {
    /**面谈*/
    void confer();
    /**签合同*/
    void signContract();
    /**订票*/
    void bookTicket();
    /**唱歌*/
    void sing();
    /**收尾款*/
    void collectMoney();
}

真实类

public class RealStar implements Star{
    @Override
    public void confer() {
        System.out.println("RealStar confer");
    }

    @Override
    public void signContract() {
        System.out.println("RealStar signContract");
    }

    @Override
    public void bookTicket() {
        System.out.println("RealStar bookTicket");
    }

    @Override
    public void sing() {
        System.out.println("RealStar sing");
    }

    @Override
    public void collectMoney() {
        System.out.println("RealStar collectMoney");
    }
}

代理类

public class ProxyStar implements Star{
    // 持有真实类的引用
    private Star star;

    public ProxyStar(Star star) {
        this.star = star;
    }

    @Override
    public void confer() {
        System.out.println("ProxyStar confer");
    }

    @Override
    public void signContract() {
        System.out.println("ProxyStar signContract");
    }

    @Override
    public void bookTicket() {
        System.out.println("ProxyStar bookTicket");
    }

    @Override
    public void sing() {
        // 调用真实类的方法
        star.sing();
    }

    @Override
    public void collectMoney() {
        System.out.println("ProxyStar collectMoney");
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Star real = new RealStar();
        Star proxy = new ProxyStar(real);

        proxy.confer();
        // 代理类调用真实类的方法
        proxy.sing();
    }
}

7 动态代理模式

jdk自带动态代理:
java.lang.reflect.Proxy
动态生成代理类和对象

java.lang.reflect.InvocationHandler
处理器接口
通过invoke方法实现对真实角色的代理访问
每次通过Proxy生成代理类对象都要指定对应的处理器对象

接口

public interface Star {
    /**唱歌*/
    void sing();
}

真实对象

public class RealStar implements Star{
    @Override
    public void sing() {
        System.out.println("RealStar sing");
    }
}

处理器对象

public class StarHandler implements InvocationHandler {
    Star realStar;

    public StarHandler(Star realStar) {
        this.realStar = realStar;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 每次调代理类方法都进到该方法,可进行统一流程控制
        Object object = null;
        System.out.println("面谈...签合同...订机票...");
        if(method.getName().equals("sing")) {
           object =  method.invoke(realStar, args);
        }
        System.out.println("收尾款...");
        return object;
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Star realStar = new RealStar();
        StarHandler handler = new StarHandler(realStar);
        Star proxy = (Star) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler);
        proxy.sing();
    }
}

场景:
Struts2拦截器
数据库连接池关闭
Hibernate延迟加载
mybatis拦截器插件
AspectJ
spring aop 日志/声明式事务
web service
RMI
随便选择一个技术框架都有代理模式

8 桥接模式

类膨胀问题
联想笔记本 联想台式机 联想平板
华为笔记本 华为台式机 华为平板
...
通过电脑持有品牌对象实现桥接

/**
 * 品牌
 */
public interface Brand {
    void sale();
}

class Lenovo implements Brand {
    @Override
    public void sale() {
        System.out.println("销售联想电脑");
    }
}

class Dell implements Brand {
    @Override
    public void sale() {
        System.out.println("销售戴尔电脑");
    }
}

public class Computer {
    // 持有品牌对象
    protected Brand brand;

    public Computer(Brand brand) {
        this.brand = brand;
    }

    public void sale() {
        brand.sale();
    }
}

class Desktop extends Computer {

    public Desktop(Brand brand) {
        super(brand);
    }

    @Override
    public void sale() {
        System.out.println("销售台式机");
    }
}

class Laptop extends Computer {

    public Laptop(Brand brand) {
        super(brand);
    }

    @Override
    public void sale() {
        System.out.println("销售笔记本");
    }
}
public class Client {
    public static void main(String[] args) {
        // 销售联想笔记本
        // 用组合代替集成关系
        Computer computer = new Laptop(new Lenovo());
        computer.sale();
    }
}

场景(多个变化维度):
JDBC

银行日志管理两个维度
格式分类 操作 交易 异常
距离分类 本地 异地

人力资源系统奖金计算
奖金分类 个人 团体 激励
部门分类 人事 销售 研发

OA消息处理
业务类型 普通 加急 特急
发送方式 系统内 短信 邮件

9 组合模式

场景

部分和整体关系用树状结构表示,从而客户端可以使用统一的方式处理部分和整体对象

模拟杀毒软件架构设计
public interface AbstractFile {
    void killVirus();
}

class ImageFile implements AbstractFile {
    private String name;

    public ImageFile(String name) {
        this.name = name;
    }

    @Override
    public void killVirus() {
        System.out.println("图像文件 " + name + " 进行查杀");
    }
}

class TextFile implements AbstractFile {
    private String name;

    public TextFile(String name) {
        this.name = name;
    }

    @Override
    public void killVirus() {
        System.out.println("文本文件 " + name + " 进行查杀");
    }
}

class Folder implements AbstractFile {
    private String name;
    // 定义容器,用来存放容器子节点
    private List<AbstractFile> list = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    public void add(AbstractFile file) {
        list.add(file);
    }

    public void remove(AbstractFile file) {
        list.remove(file);
    }

    public AbstractFile getChild(int index) {
        return list.get(index);
    }

    @Override
    public void killVirus() {
        System.out.println("文件夹 " + name + " 进行查杀");
        for(AbstractFile file : list) {
            // 天然递归
            file.killVirus();
        }
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        AbstractFile f2, f3, f5, f6;
        Folder f1 = new Folder("我的收藏");
        f2 = new ImageFile("头像.jpg");
        f3 = new TextFile("1.txt");

        f1.add(f2);
        f1.add(f3);

//        f1.killVirus();
//        f2.killVirus();

        Folder f4 = new Folder("图像");
        f5 = new ImageFile("1.jpg");
        f6 = new ImageFile("2.jpg");
        f4.add(f5);
        f4.add(f6);

        f1.add(f4);

        f1.killVirus();
    }
}

应用

操作系统资源管理器
GUI容器层次图
XML文件解析
OA组织结构处理
Junit单元测试框架

10 装饰器模式

动态地为一个对象增加新的功能
无需继承增加子类,使用对象的关联关系,避免类膨胀

/**
 * 抽象组件
 */
public interface ICar {
    void move();
}

/**
 * 具体构建对象
 */
class Car implements ICar {

    @Override
    public void move() {
        System.out.println("陆地上跑");
    }
}

/**
 * 装饰器对象
 */
class SuperCar implements ICar {
    protected ICar car;

    public SuperCar(ICar car) {
        this.car = car;
    }

    @Override
    public void move() {
        car.move();
    }
}

class FlyCar extends SuperCar {

    public FlyCar(ICar car) {
        super(car);
    }

    public void fly() {
        System.out.println("飞");
    }

    @Override
    public void move() {
        super.move();
        fly();
    }
}

class WaterCar extends SuperCar {

    public WaterCar(ICar car) {
        super(car);
    }

    public void swim() {
        System.out.println("游");
    }

    @Override
    public void move() {
        super.move();
        swim();
    }
}

class AICar extends SuperCar {

    public AICar(ICar car) {
        super(car);
    }

    public void autoMove() {
        System.out.println("自动驾驶");
    }

    @Override
    public void move() {
        super.move();
        autoMove();
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Car car = new Car();
        car.move();

        // 增加飞行功能
        FlyCar flyCar = new FlyCar(car);
        flyCar.move();

        // 增加水里游功能(复合功能)
        WaterCar waterCar = new WaterCar(flyCar);
        waterCar.move();
    }
}
应用

IO流
Servlet API中Request对象HttpServletRequestWrapper(关键词Wrapper)

缺点

产生很多小对象,影响性能
易于出错,调试麻烦

装饰模式和桥接模式区别

桥接模式是沿多个维度变化,装饰模式是增加新功能

11 外观(门面)模式

迪米特法则:
一个实体应尽量少地与其他实体发生相互作用

public class Gongshang {
    public void kaihu() {
        System.out.println("工商局开户");
    }
}

public class Shuiwu {
    public void baoshui() {
        System.out.println("税务局报税");
    }
}

public class Yinhang {
    public void kaihu() {
        System.out.println("银行开户");
    }
}

门面对象

public class RegisterFacade {
    public void register() {
        Gongshang gongshang = new Gongshang();
        gongshang.kaihu();
        Yinhang yinhang = new Yinhang();
        yinhang.kaihu();
        Shuiwu shuiwu = new Shuiwu();
        shuiwu.baoshui();
    }
}

客户端

/**
 * 客户端只与门面对象打交道
 */
public class Client {
    public static void main(String[] args) {
        RegisterFacade registerFacade = new RegisterFacade();
        registerFacade.register();
    }
}

各种框架都会用到:
commons提供的DBUtils类
Hibernate提供的工具类
Spring JDBC工具类

12 享元模式

很多个相同或相似对象通过享元模式节省内存
高效支持大量细粒度对象重用

场景

围棋棋子,内部状态(颜色)共享,外部状态(坐标)作为参数传入

/**
 * 享元类
 */
public interface ChessFlyWeight {
    void setColor(String color);
    String getColor();
    void display(Coordinate c);
}

class ConcreteChess implements ChessFlyWeight {
    private String color;

    public ConcreteChess(String color) {
        this.color = color;
    }

    @Override
    public void setColor(String color) {
        this.color = color;
    }

    @Override
    public String getColor() {
        return color;
    }

    @Override
    public void display(Coordinate c) {
        System.out.println("棋子颜色:" + color);
        System.out.println("棋子坐标:" + c.getX() + "," + c.getY());
    }
}

public class Coordinate {
    private int x, y;

    public Coordinate(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

享元工厂

/**
 * 享元工厂类
 */
public class ChessFlyWeightFactory {
    // 享元池
    private static Map<String, ChessFlyWeight> map = new HashMap<>();

    public static ChessFlyWeight getChess(String color) {
        if(map.get(color) != null) {
            return map.get(color);
        } else {
            ChessFlyWeight chessFlyWeight = new ConcreteChess(color);
            map.put(color, chessFlyWeight);
            return chessFlyWeight;
        }
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        ChessFlyWeight chess1 = ChessFlyWeightFactory.getChess("黑色");
        ChessFlyWeight chess2 = ChessFlyWeightFactory.getChess("黑色");
        System.out.println(chess1 == chess2);

        // 增加外部状态处理
        chess1.display(new Coordinate(10, 10));
        chess2.display(new Coordinate(20, 20));
    }
}
应用

线程池 数据库连接池
String类的设计(共享常量池)

13 责任链模式

行为模式关注对象交互
责任链模式将能够处理同一请求的对象连成链

场景

打牌轮流出牌
公司公文审批

/**
 * 封装请假基本信息
 */
public class LeaveRequest {
    private String empName;
    private int leaveDays;
    private String reason;

   // 有参构造器/getter/setter...
}

责任链
关系可以实时修改

/**
 * 抽象类
 */
public abstract class Leader {
    protected String name;
    protected Leader nextLeader;

    public Leader(String name) {
        this.name = name;
    }

    /**
     * 设置责任链后继对象
     * @param nextLeader
     */
    public void setNextLeader(Leader nextLeader) {
        this.nextLeader = nextLeader;
    }

    /**
     * 处理请求的核心业务方法
     * @param leaveRequest
     */
    public abstract void handleRequest(LeaveRequest leaveRequest);
}

class Director extends Leader {
    public Director(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getLeaveDays() < 3) {
            System.out.println("员工:" + leaveRequest.getEmpName() +
                    "请假, 天数:"+leaveRequest.getLeaveDays());
            System.out.println("主任:" + this.name + "审批通过");
        } else if(this.nextLeader != null) {
            this.nextLeader.handleRequest(leaveRequest);
        }
    }
}

class Manager extends Leader {
    public Manager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getLeaveDays() >= 3 && leaveRequest.getLeaveDays() < 10) {
            System.out.println("员工:" + leaveRequest.getEmpName() +
                    "请假, 天数:"+leaveRequest.getLeaveDays());
            System.out.println("经理:" + this.name + "审批通过");
        } else if(this.nextLeader != null) {
            this.nextLeader.handleRequest(leaveRequest);
        }
    }
}

class GeneralManager extends Leader {
    public GeneralManager(String name) {
        super(name);
    }

    @Override
    public void handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getLeaveDays() >= 10) {
            System.out.println("员工:" + leaveRequest.getEmpName() +
                    "请假, 天数:"+leaveRequest.getLeaveDays());
            System.out.println("总经理:" + this.name + "审批通过");
        } else if(this.nextLeader != null) {
            System.out.println("辞退!");
        }
    }
}

客户端

public class Client {
    public static void main(String[] args) {
        Leader a = new Director("张三");
        Leader b = new Manager("李四");
        Leader c = new GeneralManager("王五");
        a.setNextLeader(b);
        b.setNextLeader(c);
        LeaveRequest leaveRequest = new LeaveRequest("Tom", 10, "相亲");
        a.handleRequest(leaveRequest);
    }
}

通过集合\数组生成责任链更加实用
应用:
异常机制
js事件冒泡和捕获机制
Servlet过滤器
Struts2拦截器

14 迭代器(游标 cursor)模式

场景

提供一种可以遍历聚合对象的方式

/**
 * 自定义迭代器接口
 */
public interface MyIterator {
    void first();
    void next();
    boolean hasNext();
    boolean isFirst();
    boolean isLast();
    Object getCurrent();
}

/**
 * 自定义聚合类
 */
public class ConcreteMyAggregate {
    private List<Object> list = new ArrayList<>();

    /**
     * 获得迭代器
     * @return
     */
    public MyIterator createIterator() {
        return new ConcreteIterator();
    }

    public void addObj(Object obj) {
        list.add(obj);
    }

    public void removeObj(Object obj) {
        list.remove(obj);
    }

    public List<Object> getList() {
        return list;
    }

    public void setList(List<Object> list) {
        this.list = list;
    }

    private class ConcreteIterator implements MyIterator {
        private int curcor;

        @Override
        public void first() {
            curcor = 0;
        }

        @Override
        public void next() {
            if(curcor < list.size()) {
                curcor++;
            }
        }

        @Override
        public boolean hasNext() {
            if(curcor < list.size()) {
                return true;
            }
            return false;
        }

        @Override
        public boolean isFirst() {
            return curcor == 0 ? true : false;
        }

        @Override
        public boolean isLast() {
            return curcor == list.size()-1 ? true : false;
        }

        @Override
        public Object getCurrent() {
            return list.get(curcor);
        }
    }
}

public class Client {
    public static void main(String[] args) {
        ConcreteMyAggregate concreteMyAggregate = new ConcreteMyAggregate();
        concreteMyAggregate.addObj("aa");
        concreteMyAggregate.addObj("bb");
        concreteMyAggregate.addObj("cc");

        MyIterator iter = concreteMyAggregate.createIterator();
        while(iter.hasNext()) {
            System.out.println(iter.getCurrent());
            iter.next();
        }
    }
}

应用

Java Set/List的迭代器

相关文章

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 设计模式笔记汇总

    目录 设计原则 “依赖倒置”原则 未完待续... 设计模式 设计模式——策略模式 设计模式——装饰者模式 设计模式...

  • 设计模式

    《C#设计模式》 《C#设计模式》-设计模式概述 《C#设计模式》-面向对象设计原则 《C#设计模式》-单例模式 ...

  • 浅谈JS的一些设计模式

    @(书籍阅读)[JavaScript, 设计模式] 常见设计模式 设计模式简介 设计模式概念解读 设计模式的发展与...

  • 前端设计模式

    JS设计模式一:工厂模式jS设计模式二:单例模式JS设计模式三:模块模式JS设计模式四:代理模式JS设计模式五:职...

  • 设计模式之工厂模式

    设计模式之工厂模式 标签(空格分隔): 设计模式 工厂模式 设计模式的感念 设计模式的应用 工厂设计模式的产生 工...

  • JavaJavascript基础进阶(十七)JS中常用的设计模式

    单利设计模式、构造原型设计模式、发布订阅设计模式、promise设计模式 单利模式 构造原型设计模式 最贴近OOP...

  • 设计模式 - 目录

    设计模式01 - 单例模式 设计模式02 - 工厂模式 设计模式03 - 建造者模式 设计模式04 - 适配器模式...

  • 第1章 设计模式概述

    一、设计模式的概念 二、设计模式的历史 三、设计模式的要素 四、设计模式的分类 ■ 创建型设计模式 ■ 结构型设计...

  • iOS设计模式(3)适配器模式

    设计模式系列文章 《iOS设计模式(1)简单工厂模式》《iOS设计模式(2)工厂模式》《iOS设计模式(4)抽象工...

网友评论

      本文标题:设计模式

      本文链接:https://www.haomeiwen.com/subject/hlvdmktx.html