《架构师训练营》-第三周-设计模式-待更新

课堂内容

学习代码:https://github.com/CNXMBuyu/design-pattern-study.git

简单工厂

package cn.hgy.simplefactory;

/**
 * @author guoyu.huang
 * @version 1.0.0
 */
public class SimpleFactory {

    public BaseClass getClass(String type) {
        String classAType = "classA";
        if (classAType.equals(type)) {
            return new ClassA();
        } else {
            return new ClassB();
        }
    }
}

如果要增加类型,需要更新工厂代码,不符合开闭原则。解决方案如下:

工厂模式

工厂接口


package cn.hgy.factory;

/**
 * @author guoyu.huang
 * @version 1.0.0
 */
public abstract class BaseFactory {

    protected abstract boolean handle(String type);

    public abstract BaseClass create();
}

工厂接口实现

package cn.hgy.factory;

/**
 * @author guoyu.huang
 * @version 1.0.0
 */
public class ClassAFactory extends BaseFactory {

    private static final String CLASS_A_TYPE = "classA";

    @Override
    public boolean handle(String type) {
        return CLASS_A_TYPE.equals(type);
    }

    @Override
    public BaseClass create() {
        return new ClassA();
    }
}

工厂类

package cn.hgy.factory;


import java.io.File;
import java.util.*;

/**
 * @author guoyu.huang
 * @version 1.0.0
 */
public class Factory {

    public BaseClass getClass(String type) {

        List<BaseFactory> factoryList = getAllClass();
        for(BaseFactory baseFactory : factoryList) {
            if(baseFactory.handle(type)){
                return baseFactory.create();
            }
        }
        return null;
    }

    /**
     * 根据反射获取所有的工厂类
     * @return
     */
    private List<BaseFactory> getAllClass(){
        File directory = new File("D:\\codespace\\design-pattern-study\\factory\\target\\classes\\cn\\hgy\\factory");
        File[] files = directory.listFiles();

        List<BaseFactory> factoryList = new ArrayList<>();
        for (File file : files) {
            String filePath = file.getPath().replace("D:\\codespace\\design-pattern-study\\factory\\target\\classes\\", "");
            filePath = filePath.replaceAll(".class", "");
            filePath = filePath.replaceAll("\\\\", ".");

            try {
                Class clazz = Class.forName(filePath);
                if(clazz.getSuperclass() != null && clazz.getSuperclass().equals(BaseFactory.class)){
                    BaseFactory factory = (BaseFactory)Class.forName(filePath).newInstance();
                    factoryList.add(factory);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return factoryList;
    }
}

如果使用spring,做法则更简单,代码如下:


@Component
public class ClassAFactory extends BaseFactory {
    // something
}


/**
 * @author guoyu.huang
 * @version 1.0.0
 */
@Component
public class Factory {

    @Autowired
    private List<BaseFactory> factoryList;

    public BaseClass getClass(String type) {

        for(BaseFactory baseFactory : factoryList) {
            if(baseFactory.handle(type)){
                return baseFactory.create();
            }
        }
        return null;
    }
}

使用工厂实现简单spring工厂,参考地址:https://github.com/CNXMBuyu/design-pattern-study.git

单例模式

饿汉式

package cn.hgy.single.eager;

/**
 * 饿汉单例模式,先实例化
 *
 * @author guoyu.huang
 * @version 1.0.0
 */
public class EagerSingleton {

    private static EagerSingleton eagerSingleton = new EagerSingleton();

    private EagerSingleton(){

    }

    public static EagerSingleton getInstance(){
        return eagerSingleton;
    }
}

懒汉式

package cn.hgy.single.lazy;

/**
 * 懒汉单例模式,需要的时候实例化
 *
 * @author guoyu.huang
 * @version 1.0.0
 */
public class LazySingleton {

    private static LazySingleton instance;

    private LazySingleton() {

    }

    public static LazySingleton getInstance() {
        if (instance == null) {
            return new LazySingleton();
        } else {
            return instance;
        }
    }
}

双重校验

package cn.hgy.single.doublecheck;

/**
 * 双重校验单例模式
 *
 * @author guoyu.huang
 * @version 1.0.0
 */
public class DoubleCheckSingleton {

    private static volatile DoubleCheckSingleton instance;

    private DoubleCheckSingleton() {
    }

    public static DoubleCheckSingleton getInstance() {
        if (instance == null) {
            synchronized (DoubleCheckSingleton.class) {
                if(instance == null){
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

内部类

效果等同于双重校验

package cn.hgy.single.inner;

import cn.hgy.single.doublecheck.DoubleCheckSingleton;

/**
 * @author guoyu.huang
 * @version 1.0.0
 */
public class InnerSingleton {

    private InnerSingleton(){}

    public static InnerSingleton getInstance() {
        return Singleton.instance;
    }

    private static class Singleton{
        private static final InnerSingleton instance = new InnerSingleton();
    }
}

适配器模式

适配器模式是为了原本由于接口不兼容而不能一起工作的类可以一起工作。

通用代码-基础类


public interface OldInterface {

    void invoke(OldParameter parameter);
}


public class OldInterfaceImpl implements OldInterface{

    @Override
    public void invoke(OldParameter parameter) {
        System.out.println(parameter.toString());
    }
}


public class OldParameter {

    private String a;
    private String b;

    // 省略get和set
}

public interface NewInterface {

    void invoke(NewParameter parameter);
}


public class NewParameter {

    private String newA;
    private String newB;
    
    // 省略get和set
}

类适配器

当新接口和老接口提供的函数大部分相同时,可以使用类适配器来提高代码的复用率。否则建议使用对象适配器,避免接口暴露太多不可用的接口,降低接口的易用性。

public class ClassAdapter extends OldInterfaceImpl implements NewInterface{

    @Override
    public void invoke(NewParameter parameter) {
        OldParameter oldParameter = new OldParameter();
        oldParameter.setA(parameter.getNewA());
        oldParameter.setB(parameter.getNewB());
        super.invoke(oldParameter);
    }
}

对象适配器

只暴露合适的接口,再通过组合的方式来提高代码的复用率。

public class ObjectAdapter implements NewInterface{

    private OldInterface oldInterface = new OldInterfaceImpl();

    @Override
    public void invoke(NewParameter parameter) {
        OldParameter oldParameter = new OldParameter();
        oldParameter.setA(parameter.getNewA());
        oldParameter.setB(parameter.getNewB());
        oldInterface.invoke(oldParameter);
    }
}

通用代码-调用类

public class Main {

    public static void main(String[] args) {
        NewParameter parameter = new NewParameter();
        parameter.setNewA("a");
        parameter.setNewB("b");
        new ClassAdapter().invoke(parameter);
        new ObjectAdapter().invoke(parameter);
    }
}

模板模式

什么是模板模式

将算法整体架构定义好,让子类在不改变算法整体结构的情况下,重新定义算法中的某些步骤。

为什么使用模板模式

代码复用

如何使用模板模式

定义算法整体架构(抽象类),将需要子类来实现的方法定义为抽象方法。

public abstract class Player {

    public void initPlayer() {
        // 保存玩家信息
        savePlayer();
        // 初始化玩家数据,因为每款游戏都不同,所以需要有子类具体实现
        initData();
    }

    protected void savePlayer() {
        System.out.println("已保存玩家信息");
    }

    /**
     * 初始化玩家数据
     */
    protected abstract void initData();

}

public class GamePlayer extends Player {

    @Override
    protected void initData() {
        System.out.println("初始化游戏玩家");
    }
}

相似功能:回调

A类事先注册某个函数F到B类,A类在调用B类的P函数的时候,B类反过来调用A类注册给它的F函数。

public class Player {

    public void initPlayer(PlayerCallback playerCallback){
        // 保存玩家信息
        savePlayer();
        // 初始化玩家数据,因为每款游戏都不同,所以需要有子类具体实现
        playerCallback.initData();
    }

    protected void savePlayer(){
        System.out.println("已保存玩家信息");
    }
}

public interface PlayerCallback {

    /**
     * 初始化玩家数据
     */
    void initData();
}

// 调用类
public class Main {

    public static void main(String[] args) {
        Player player = new Player();
        player.initPlayer(new PlayerCallback() {
            @Override
            public void initData() {
                System.out.println("初始化游戏玩家数据");
            }
        });
    }
}

回调函数的经典案例:spring的JdbcTemplate

模板模板是使用继承来实现,而回调函数是使用组合来实现。

组合模式

装饰者模式

装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。

通用代码-基础类

public interface IBusinessService {

    void invoke();

    void invoke2();
}


public class BusinessService implements IBusinessService{

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

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

现在需要对invoke函数增加记录操作的功能。

装饰器思路

继承相同接口,将原始类当作参数传入,增强功能。

public class OperationService implements IBusinessService {

    private IBusinessService businessService;

    // 这里通过构造函数参数
    public OperationService(IBusinessService businessService) {
        this.businessService = businessService;
    }

    @Override
    public void invoke() {
        businessService.invoke();
        // 增强功能
        System.out.println("operation");
    }

    @Override
    public void invoke2() {
        businessService.invoke2();
    }
}

通用代码-调用类

public class Main {

    public static void main(String[] args) {
        IBusinessService businessService = new BusinessService();
        // 注意,这里传入的实参
        IBusinessService operationService = new OperationService(businessService);
        operationService.invoke();
    }
}

延申阅读

spring中的设计模式

控制反转

Service依赖Repository,原先是在Service中实例化Repository,现在将实例化的动作放在容器中实现。

单例模式

SpringMVC

分布式事务

  1. 事务补偿机制和回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

瑾析编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值