设计模式

本文深入探讨了设计模式的六大原则,并通过实例展示了单例模式、工厂模式(工厂方法和抽象工厂)、观察者模式和代理模式的应用。在仓库系统服务的场景中,详细阐述了如何利用这些模式实现灵活的扩展性和解耦。此外,还介绍了装饰器模式在生成随机字符串功能中的应用,展示了如何动态添加职责以实现不同行为。
摘要由CSDN通过智能技术生成

设计模式六大原则

  • 单一原则:一个类中只完成一件/类事情,那么引起当前类发现改变的原因就只有一个,如果有多个则有可能在修改某一类功能时影响到其它功能

  • 开闭原则:通过扩展实体类的行为来实现新的功能,而不是修改已有代码来实现变化新的功能,避免了对原有功能的破坏

  • 里氏替换原则:运行时才可确定父类的子类类型并用子类实例来替换父类实例

  • 依赖倒置原则:

  • 迪米特原则:一个对象应该对其它对象有最少的了解,只关注public修饰的方法

  • 接口隔离原则:创建接口时应尽量细化接口的抽象方法,做到实现类继承接口后所重写的方式都是该类所需要的

常用设计模式

单例模式

/**
 * 单例模式:一个类只能被实例化一次,有效避免jvm频繁回收同一个对象
 */
public class Singleton {
    // 私有化构造函数,防止通过构造函数创建实例
    private Singleton() {}

    // 静态内部类
    // 类的静态属性只会在第一次加载类的时候初始化,所以在这里JVM帮助我们保证了线程的安全性
    // 利用静态内部类特点实现延迟加载,效率高
    private static class SingletonInstance {
        private static final Singleton INSTANCE = new Singleton();
    }

    // 静态内部类方式在 Singleton 类被装载时并不会立即实例化,而是在调用 getInstance 方法时才会装载 SingletonInstance 类,从而完成 Singleton 的实例化
    public static synchronized Singleton getInstance() {
        return SingletonInstance.INSTANCE;
    }

    public static void main(String[] args) {
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
    }
}

提示:Spring中可以使用@Configuration和@Bean注解自定义bean并纳入容器进行管理,默认为单例模式

工厂模式【工厂方法和抽象工厂】

工厂方法模式(简单工产模式的演变):通过依赖倒置原则动态获取接口的实例对象,弥补了简单工厂模式的缺点:
(1)工厂方法只有一个抽象工厂类和一个抽象产品类
    抽象工厂可以派生出多个具体工厂类,每个具体工厂类只能创建一个具体产品类
    抽象产品可以派生出多个具体产品类
 抽象工厂模式(工厂方法模式的演变):工厂方法模式与抽象工厂模式的区别在于:
 (2)抽象工厂只有一个抽象工厂类和多个抽象产品类(产品族)
     抽象工厂类可以派生出多个具体工厂类,每个具体工厂类可以创建多个具体产品类
     每个抽象产品类可以派生出多个具体产品类

在这里插入图片描述

抽象工厂

/**
 * TODO 仓库系统服务商接口,这里定义了仓库系统中所涉及到的所有接口。
 * 缺点:如果一个类不是抽象类,要实现一个接口,那必须要实现该接口里面的所有方法
 */
public interface WarehouseSystemFactory {
    /**
     * 查询仓库列表:获取仓库的编码和id
     */
    public void queryWarehouseList();

    /**
     * 查询仓库的运输渠道列表:获取运输渠道的编码和id
     */
    public void queryWarehouseShipMethodList();

    /**
     * 查询仓库的商品列表:获取商品的编码和id
     */
    public void queryWarehouseSkuList();

    /**
     * 查询库存
     */
    public void queryInventory();

    /**
     * 创建出库单
     */
    public void createOutOrder();

    /**
     * 查询出库单:订单的状态
     */
    public void queryOutOrder();

    /**
     * 查询出库单的物流信息:订单的跟踪号
     */
    public void queryOutOrderLogistics();

}

抽象产品(继承抽象工厂)

/**
 * TODO 仓库系统服务商关于【出库单】的抽象产品类。
 * 优点1:如果一个类是抽象类,要实现一个接口,那么不必实现接口里面的每一个方法,实现抽象方法与实现类的解耦
 * 优点2:当某个新的仓库实例需要更多的接口来实现辅助功能时,只需要分别在"抽象工厂"和"抽象产品"中添加新的接口即可
 */
public abstract class WarehouseSystemProduct implements WarehouseSystemFactory {
    /**
     * 查询库存
     */
    @Override
    public void queryInventory() {
        System.out.println("你还没有对接queryInventory接口");
    }

    /**
     * 创建出库单
     */
    @Override
    public void createOutOrder() {
        System.out.println("你还没有对接createOutOrder接口");
    }

    /**
     * 查询出库单:订单的状态
     */
    @Override
    public void queryOutOrder() {
        System.out.println("你还没有对接queryOutOrder接口");
    }

    /**
     * 查询出库单的物流信息:订单的跟踪号
     */
    @Override
    public void queryOutOrderLogistics() {
        System.out.println("你还没有对接queryOutOrderLogistics接口");
    }

    /**
     * 查询仓库列表:获取仓库的编码和id
     */
    @Override
    public void queryWarehouseList() {
        System.out.println("你还没有对接queryWarehouseList接口");
    }

    /**
     * 查询仓库的运输渠道列表:获取运输渠道的编码和id
     */
    @Override
    public void queryWarehouseShopMethodList() {
        System.out.println("你还没有对接queryWarehouseShopMethodList接口");
    }

    /**
     * 查询仓库的商品列表:获取商品的编码和id
     */
    @Override
    public void queryWarehouseSkuList() {
        System.out.println("你还没有对接queryWarehouseSkuList接口");
    }
}

YeJoin仓库系统服务商

/**
 * YeJoin仓库系统服务商接口 TODO 根据自身条件实现 WarehouseSystemProduct 抽象产品即可
 */
public class YeJoinFactory extends WarehouseSystemProduct {
    private WarehouseSystemProduct warehouseSystemProduct;

    public YeJoinFactory() {}
    public YeJoinFactory(WarehouseSystemProduct warehouseSystemProduct) {
        this.warehouseSystemProduct = warehouseSystemProduct;
    }

    /**
     * 查询库存
     */
    @Override
    public void queryInventory() {
        this.warehouseSystemProduct.queryInventory();
    }

    /**
     * 创建出库单
     */
    @Override
    public void createOutOrder() {
        this.warehouseSystemProduct.createOutOrder();
    }

    /**
     * 查询出库单:订单的状态
     */
    @Override
    public void queryOutOrder() {
        this.warehouseSystemProduct.queryOutOrder();
    }
}

YeJoin下的HuaXia仓库实例产品

/**
 * YeJoin仓库系统服务商下的HuaXia仓库实例
 */
public class YeJoinForHuaXiaProduct extends WarehouseSystemProduct {
    /**
     * 查询库存
     */
    @Override
    public void queryInventory() {
        System.out.println("YeJoinForHuaXiaProduct queryInventory");
    }

    /**
     * 创建出库单
     */
    @Override
    public void createOutOrder() {
        System.out.println("YeJoinForHuaXiaProduct createOutOrder");
    }

    /**
     * 查询出库单:订单的状态
     */
    @Override
    public void queryOutOrder() {
        System.out.println("YeJoinForHuaXiaProduct createOutOrder");
    }
}

YeJoin下的Hwc仓库实例产品

/**
 * YeJoin仓库系统服务商下的Hwc仓库实例
 */
public class YeJoinForHwcProduct extends WarehouseSystemProduct {
    /**
     * 查询库存
     */
    @Override
    public void queryInventory() {
        System.out.println("YeJoinForHwcProduct queryInventory");
    }

    /**
     * 创建出库单
     */
    @Override
    public void createOutOrder() {
        System.out.println("YeJoinForHwcProduct createOutOrder");
    }

    /**
     * 查询出库单:订单的状态
     */
    @Override
    public void queryOutOrder() {
        System.out.println("YeJoinForHwcProduct queryOutOrder");
    }
}

调用案例

public class Run {
    public static void main(String[] args) {
        // 输出:YeJoinForHuaXiaProduct queryInventory
        new YeJoinFactory(new YeJoinForHuaXiaProduct()).queryInventory();

        // 输出:YeJoinForHwcProduct queryInventory
        new YeJoinFactory(new YeJoinForHwcProduct()).queryInventory();

        // 你还没有对接queryOutOrderLogistics接口
        new YeJoinFactory(new YeJoinForHwcProduct()).queryOutOrderLogistics();
    }
}

总结

1、仓库系统服务商可以无限横向扩展
2、每个仓库系统服务商下的仓库实例可以无限横向扩展

观察者模式

需求:创建出库单成功以后,我司erp需要操作库存和变更订单状态

/**
 * 被观察者(广播):向所有订阅该广播的观察者发送消息
 *  出库单创建成功后需要:修改订单状态、修改库存、添加日志等等
 */
public class CreateOutOrderObservable extends Observable {
    /**
     * 注册观察者
     */
    public void registerObserved(Observer observer) {
        this.addObserver(observer);
    }

    /**
     * 创建出库订单成功,通知相关观察者
     */
    public void createOutOrderSuccessHandle(Object object) {
        // set changed = true
        this.setChanged();
        // callback observable objects
        this.notifyObservers(object);
    }

}
/**
 * 观察者(订阅者):订单
 */
public class OrderObserver implements Observer {
    @SneakyThrows
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(MessageFormat.format("{0} 更新订单---->", arg.toString()));
    }
}

/**
 * 观察者(订阅者):库存
 */
public class StockObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(MessageFormat.format("{0} 更新库存---->", arg.toString()));
    }
}
# 测试
public class DemoClient {

    public static void main(String[] args) {
        // 创建订单观察者
        OrderObserver orderObserver = new OrderObserver();
        // 创建库存观察者
        StockObserver stockObserver = new StockObserver();
        
        // 创建被观察者
        CreateOutOrderObservable createOutOrderObservable = new CreateOutOrderObservable();
        // 注册订单观察者
        createOutOrderObservable.registerObserved(orderObserver);
        // 注册库存观察者
        createOutOrderObservable.registerObserved(stockObserver);
        // 通知相关观察者
        createOutOrderObservable.createOutOrderSuccessHandle("createOutOrder Success!");
    }
}

提示:Spring框架中也有提供相关机制来实现观察者模式:pushEvent事件传播机制

代理模式

需求:默认创建出库单时没有记录相关参数,现需要记录创建出库单操作的入参、出参

public interface Demo6Service {
    String createOutOrder(String orderId);
}

@Service
public class Demo6ServiceImpl implements Demo6Service {
    @Override
    public String createOutOrder(String orderId) {
        return "orderId";
    }
}
@Service
@Slf4j
public class Demo6ServiceProxyImpl implements Demo6Service {
    private Demo6ServiceImpl demo6ServiceImpl;

    public Demo6ServiceProxyImpl(Demo6ServiceImpl demo6ServiceImpl) {
        this.demo6ServiceImpl = demo6ServiceImpl;
    }

    @Override
    public String createOutOrder(String orderId) {
        String outOrderId = demo6ServiceImpl.createOutOrder(orderId);
        log.info("入参:{}", orderId);
        log.info("出参:{}", outOrderId);
        return outOrderId;
    }
}

适配器模式

需求:大部分仓库在查询出库单详情的时候会返回订单的物流跟踪号,但极少部分仓库是没有返回的,只是单提供了查询物流跟踪号的接口,所以这里我们使用适配器模式(适配出库单详情接口来拿到物流跟踪号)

/**
 * 抽象接口类
 */
public interface WareHouseService {
    Map<String,String> getOutOrder(String outOrderId);
}

/**
 * 抽象类(避免继承抽象接口类后过度实现接口中的所有方法)
 */
public class WareHouseAbstract implements WareHouseService {
    @Override
    public Map<String,String> getOutOrder(String outOrderId) {
        return null;
    }
}

/**
 * 抽象类的具体实现类:猩猩国际仓库(查询出库订单)
 */
public class WareHouseXxgjImpl extends WareHouseAbstract {
    @Override
    public Map<String,String> getOutOrder(String outOrderId) {
        Map<String,String> orderMap = new HashMap<>();
        orderMap.put("status", "shipped");
        return orderMap;
    }
}

/**
 * 抽象类的具体实现类的适配器类:猩猩国际仓库(适配额外的查询物流功能)
 */
public class WareHouseXxgjAdapteeImpl {
    /** 查询出库单 */
    public Map<String,String> getOutOrder(String outOrderId) {
        // 查询订单状态
        Map<String,String> orderMap = new WareHouseXxgjImpl().getOutOrder(outOrderId);
        // 查询物流编码
        orderMap.put("trackNo", "跟踪号");
        return orderMap;
    }
}
/**
 * 类适配器模式:
 *   目标接口:WareHouseService
 *   适配器类:WareHouseXxgjAdapteeImpl
 *   适配器:WareHouseXxgjAdapterImpl 
 */
public class WareHouseXxgjAdapterImpl extends WareHouseXxgjAdapteeImpl implements WareHouseService {
    /** 创建出库单 */
    @Override
    public Map<String,String> getOutOrder(String outOrderId) {
        return super.getOutOrder(outOrderId);
    }
}

public class ClassApader {
    public static void main(String[] args) {
        Map<String,String> orderMap = new WareHouseXxgjAdapterImpl().getOutOrder("xxgj");
        System.out.println(JSONObject.toJSONString(orderMap));
    }
}
/**
 * 对象适配器模式:相比于类适配器,跟灵活
 *   目标接口:WareHouseService
 *   适配器类:WareHouseXxgjAdapteeImpl
 *   适配器:WareHouseXxgjAdapter2Impl 
 */
 /**
 * 接口适配器模式:
 *  当一个接口中有多个抽象方法,实现该接口的类就必须实现该接口的所有方法,
 *  然而并不是所有的方法都是我们需要的,有时只需要某一些,此处为了解决这个问题,我们引入了接口的适配器模式,
 *  借助于一个抽象类,该抽象类实现了该接口,实现了所有的方法,而我们不和原始的接口打交道,只和该抽象类取得联系
 */
public class WareHouseXxgjAdapter2Impl extends WareHouseAbstract {
    private WareHouseXxgjAdapteeImpl wareHouseXxgjAdapteeImpl;

    public WareHouseXxgjAdapter2Impl(WareHouseXxgjAdapteeImpl wareHouseXxgjAdapteeImpl) {
        this.wareHouseXxgjAdapteeImpl = wareHouseXxgjAdapteeImpl;
    }

    /** 创建出库单 */
    @Override
    public Map<String,String> getOutOrder(String wareHouseType) {
        return this.wareHouseXxgjAdapteeImpl.getOutOrder(wareHouseType);
    }
}

public class ObjectApader {
    public static void main(String[] args) {
        Map<String,String> orderMap = new WareHouseXxgjAdapter2Impl(
        														new WareHouseXxgjAdapteeImpl()).getOutOrder("xxgj");
        System.out.println(JSONObject.toJSONString(orderMap));
    }
}

装饰器模式

需求:随机生产数字和字母混合的字符串,规则任意编排且无序

public interface RandomService {
    /** 随机生产字符串 */
    String random();
}
# 抽象接口 - 实现类
@Data
public class RandomServiceImpl implements RandomService {
    private String rule;
    public RandomServiceImpl(String rule) {
        this.rule = rule;
    }
    /**
     * 随机生产字符串
     */
    @Override
    public String random() {
        System.out.println(rule);
        return "";
    }
}
# 抽象接口 - 抽象实现类
public class RandomAbstractImpl implements RandomService {
    private RandomService randomService;
    private int count;

    public RandomAbstractImpl(RandomService randomService, int count) {
        this.randomService = randomService;
        this.count = count;
    }

    /** 随机生产xxx字符串 */
    @Override
    public String random() {
        return randomService.random();
    }
}

# 抽象类 - 数字实现类
public class RandomNumImpl extends RandomAbstractImpl {
    private int count;
    public RandomNumImpl(RandomService randomService, int count) {
        super(randomService, count);
        this.count = count;
    }

    public String randomNum() {
        String strTemp = "1,2,3,4,5,6,7,8,9,0";
        StringBuilder strResult = new StringBuilder();
        for (int i = 0; i < count; i++) {
            int random = new Random().nextInt(9);
            strResult.append(strTemp.split(",")[random]);
        }
        return strResult.toString();
    }

    /**
     * 随机生产数字字符串
     */
    @Override
    public String random() {
        return super.random() + randomNum();
    }
}

# 抽象类 - 字符实现类
public class RandomLetterImpl extends RandomAbstractImpl {
    private int count;
    public RandomLetterImpl(RandomService randomService, int count) {
        super(randomService, count);
        this.count = count;
    }

    public String randomStr() {
        String strTemp = "A,B,C,D,E,F,G,H,I,G,H,I,J,K,L,M,N,O,P,Q";
        StringBuilder strResult = new StringBuilder();
        for (int i = 0; i < count; i++) {
            int random = new Random().nextInt(9);
            strResult.append(strTemp.split(",")[random]);
        }
        return strResult.toString();
    }

    /**
     * 随机生产字母字符串
     */
    @Override
    public String random() {
        return super.random() + randomStr();
    }
}
/**
     * 装饰器模式:
     *  优点:
     *      动态给对象添加一些额外的职责从而实现功能的拓展,在运行时选择不同的装饰器,从而实现不同的行为;
     *      比使用继承更加灵活,通过对不同的装饰类进行排列组合,创造出很多不同行为,得到功能更为强大的对象
     *
     *  缺点:
     *      一个装饰功能对应一个小对象,增加了系统的复杂性
     */
    public static void main(String[] args) {
        RandomAbstractImpl randomAbstractImpl1 = new RandomNumImpl(
        		new RandomLetterImpl(
          		new RandomServiceImpl("生产规则:3个数字字符串+2个字母字符串"), 3), 2);
        System.out.println(randomAbstractImpl1.random());

        RandomAbstractImpl randomAbstractImpl2 = new RandomLetterImpl(
        		new RandomNumImpl(
        				new RandomServiceImpl("生产规则:3个字母字符串 + 2个数字字符串"), 3), 2);
        System.out.println(randomAbstractImpl2.random());
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大能嘚吧嘚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值