1、构造器模式
对于构造器模式,是如果有一个对象涉及到多个参数需要设置的时候,可以使用构造器模式来构建里面的元素
比如有三个对象:
参考dolpinscheduler中的概念
流程定义
流程实例
任务实例
现在的需求是将三者封装成一个任务从Master传递到Worker,此时就可以使用构造器模式
比如构建一个TaskContext,其中包含了以上对象中的元素
然后使用一个构建一个TaskRequest使用构造器模式来构建对象
public class TaskRequest {
private TaskContext taskContext = new TaskContext();
/**
* 构建TaskRequest
* @return
*/
public static TaskRequest newBuilder() {
return new TaskRequest();
}
/**
* 设置任务相关信息
* @param task
* @return
*/
public TaskRequest setTask(Task task) {
taskContext.setTaskName(task.getTaskName());
taskContext.setTaskType(task.getTaskType());
return this;
}
/**
* 设置流程实例相关信息
* @param processInstance
* @return
*/
public TaskRequest setProcessInstance(ProcessInstance processInstance) {
taskContext.setExecuteUser(processInstance.getExecuteUser());
taskContext.setStartTime(processInstance.getStartTime());
taskContext.setEndTime(processInstance.getEndTime());
return this;
}
/**
* 设置流程定义相关信息
* @param processDefinition
* @return
*/
public TaskRequest setProcessDefinition(ProcessDefinition processDefinition) {
taskContext.setProjectName(processDefinition.getProjectName());
return this;
}
/**
* 获取任务上下文
* @return
*/
public TaskContext build() {
return taskContext;
}
}
2、组合模式 + 访问者模式
对于树形结构的id,pid形式的就可以使用组合模式 + 访问者模式
/**
* 组合模式 + 访问者模式
*/
public class CompositeDemo {
public static void main(String[] args) {
Priority root = new Priority();
root.setName("易观");
Priority dept1 = new Priority();
dept1.setName("大数据平台");
Priority dept2 = new Priority();
dept2.setName("数据平台");
List<Priority> children = new ArrayList<>();
children.add(dept1);
children.add(dept2);
root.setChildren(children);
RelatedCheckPriority relatedCheckPriority = new RelatedCheckPriority();
root.execute(relatedCheckPriority);
Boolean relateCheckResult = relatedCheckPriority.getRelateCheckResult();
// 如果都有权限,再删除
if (relateCheckResult){
RemovePriority removePriority = new RemovePriority();
root.execute(removePriority);
}
}
}
class Priority {
private String name;
private List<Priority> children = new ArrayList<>();
public void execute(PriorityOperation operation){
operation.doExecute(this);
}
}
interface PriorityOperation {
void doExecute(Priority priority);
}
class RemovePriority implements PriorityOperation{
@Override
public void doExecute(Priority priority) {
List<Priority> childrenList = priority.getChildren();
if (childrenList != null && childrenList.size() > 0){
for (Priority child : childrenList){
child.execute(this);
}
}
System.out.println("删除 : " + priority.getName());
}
}
class RelatedCheckPriority implements PriorityOperation {
/**
* 关联检查结果
*/
private Boolean relateCheckResult = false;
@Override
public void doExecute(Priority priority) {
List<Priority> childrenList = priority.getChildren();
if (childrenList != null && childrenList.size() > 0){
for (Priority child : childrenList){
child.execute(this);
}
}
// 这里需要对node进行业务判断,是否有权限
relateCheckResult = true;
}
public Boolean getRelateCheckResult() {
return relateCheckResult;
}
public void setRelateCheckResult(Boolean relateCheckResult) {
this.relateCheckResult = relateCheckResult;
}
}
3、单例
class Singleton {
/**
* 使用volatile避免指令重排
*/
private static volatile Singleton instance = null;
/**
* 构造方法私有化
*/
private Singleton(){}
/**
* 获取实例
* @return
*/
public static Singleton getInstance(){
// 比如说我线程1到这里了,然后线程1,返回的instance就会有问题
if (instance == null){
synchronized (Singleton.class){
if (instance == null){
instance = new Singleton();
/**
* 线程2执行到这里了,由于instance的指令重排
* 导致instance引用不为null,但是里面的成员是null
*/
}
}
}
return instance;
}
}
4、状态模式
在复杂状态变换的时候,使用状态模式,状态机,从一个状态到另外一个状态转换
public class Task {
private String taskName;
private String taskType;
private String state;
}
public interface TaskState {
/**
* 状态转换
* @param task
*/
void doTransform(Task task);
/**
* 判断当前状态下是否可以kill
* @param task
* @return
*/
Boolean canKill(Task task);
/**
* 判断当前状态下是否可以删除任务
* @param task
* @return
*/
Boolean canRemove(Task task);
}
public class RunningTaskState implements TaskState {
@Override
public void doTransform(Task task) {
System.out.println(task.getTaskName() + "由提交成功态到正在运行状态");
}
@Override
public Boolean canKill(Task task) {
return false;
}
@Override
public Boolean canRemove(Task task) {
return true;
}
}
public class FinishedTaskState implements TaskState {
@Override
public void doTransform(Task task) {
System.out.println(task.getTaskName() + "由正在运行状态到结束状态");
}
@Override
public Boolean canKill(Task task) {
return true;
}
@Override
public Boolean canRemove(Task task) {
return false;
}
}
public class StateManager {
public static final String SUBMITED = "submited";
public static final String RUNNING = "running";
public static final String FINISHED = "finished";
private RunningTaskState runningTaskState;
private FinishedTaskState finishedTaskState;
public StateManager(RunningTaskState runningTaskState,FinishedTaskState finishedTaskState) {
this.runningTaskState = runningTaskState;
this.finishedTaskState = finishedTaskState;
}
public void runTask(Task task) {
runningTaskState.doTransform(task);
}
public void completeTask(Task task) {
finishedTaskState.doTransform(task);
}
public Boolean canKill(Task task) {
return getTaskState(task).canKill(task);
}
public Boolean canRemove(Task task) {
return getTaskState(task).canRemove(task);
}
private TaskState getTaskState(Task task) {
if (SUBMITED.equals(task.getState())) {
return runningTaskState;
} else if (RUNNING.equals(task.getState())) {
return finishedTaskState;
}
return null;
}
}
public class StateDemo {
public static void main(String[] args) {
StateManager stateManager = new StateManager(
new RunningTaskState(),
new FinishedTaskState()
);
Task task = new Task();
task.setTaskName("测试任务");
task.setTaskType("SHELL");
task.setState(StateManager.SUBMITED);
stateManager.runTask(task);
System.out.println(stateManager.canKill(task));
System.out.println(stateManager.canRemove(task));
}
}
5、策略模式
根据不同的策略选择出来目标的ip
public class StrategyDemo {
public static void main(String[] args) {
Strategy strategy = new Strategy();
RandomSelector randomSelector = new RandomSelector();
RoundRobinSelector roundRobinSelector = new RoundRobinSelector();
String host1 = strategy.select("xx1,xx2", randomSelector);
String host2 = strategy.select("xx1,xx2", roundRobinSelector);
System.out.println(host1);
System.out.println(host2);
}
}
class Strategy {
public String select(String hosts, Selector selector) {
String host = selector.select(hosts);
return host;
}
}
interface Selector {
String select(String hosts);
}
/**
* 随机选择
*/
class RandomSelector implements Selector{
@Override
public String select(String hosts) {
return "127.0.0.1";
}
}
/**
* 轮询选择
*/
class RoundRobinSelector implements Selector {
@Override
public String select(String hosts) {
return "127.0.0.2";
}
}
6、模板方法
public class TemplateMethodDemo {
public static void main(String[] args) {
HttpServlet httpServlet = new MyHttpServlet();
httpServlet.doService("get");
}
}
abstract class HttpServlet {
public void doService(String type){
// 公共的业务逻辑
if ("get".equals(type)) {
doGet();
} else if ("post".equals(type)) {
doPost();
}
}
protected void doGet() {}
protected void doPost() {}
}
class MyHttpServlet extends HttpServlet{
@Override
protected void doGet() {
System.out.println("发送get请求");
}
}
7、迭代器模式
public class IteratorDemo {
public static void main(String[] args) {
DBManager dbManager = new DBManagerImpl();
DBIterator iterator = dbManager.iterator();
while (iterator.hasNext()){
List<String> result = iterator.next();
System.out.println(result);
}
}
}
interface DBManager {
DBIterator iterator();
}
class DBManagerImpl implements DBManager {
@Override
public DBIterator iterator() {
return new DBIteratorImpl();
}
}
interface DBIterator {
Boolean hasNext();
List<String> next();
}
class DBIteratorImpl implements DBIterator {
LinkedList<String> list = new LinkedList<>();
public DBIteratorImpl(){
list.offer("数据1");
list.offer("数据2");
list.offer("数据3");
list.offer("数据4");
}
@Override
public Boolean hasNext() {
return !list.isEmpty();
}
@Override
public List<String> next() {
ArrayList<String> dest = new ArrayList<>();
dest.add(list.poll());
dest.add(list.poll());
return dest;
}
}
8、备忘录模式
这个针对的是DS的TaskPriorityQueueImpl 和 TaskPriorityQueueConsumer
public void put(StockUpdateMessage message) throws Exception {
/**
* 每次要往内存队列放消息之前,先检查一下离线存储标识
* 如果触发了离线存储,直接就往离线存储中写入,不要走后面的逻辑了
* 写完离线存储之后,需要检查一下内存队列的大小,如果内存队列已经清零,则启动一个后台线程
* 让后台线程去将离线存储中的数据恢复写入内存队列中
*/
if (offlineStorageManager.getOffline()){
//往DB中放数据
offlineStorageManager.store(message);
if (queue.size() == 0){
new OfflineResumeThread(offlineStorageManager,this).start();
}
return;
}
// 如果内存队列已经满了,此时就触发离线存储
if (QUEUE_MAX_SIZE.equals(queue.size())){
offlineStorageManager.store(message);
offlineStorageManager.setOffline(true);
return;
}
queue.put(message);
}
OfflineResumeThread 线程:
public void run() {
try {
OfflineStorageIterator iterator = offlineStorageManager.iteartor();
// 如果表中还有数据的话
while (iterator.hasNext()){
try {
// 每次就从mysql中查询50条数据,批量查询,批量处理,批量删除
List<StockUpdateMessage> stockUpdateMessages = iterator.next();
// 将这批数据写入内存队列中
for (StockUpdateMessage message : stockUpdateMessages){
stockUpdateQueue.putDirect(message);
}
// 批量删除这批数据
offlineStorageManager.removeByBatch(stockUpdateMessages);
}catch (Exception e){
logger.error("error",e);
}
}
// 此时mysql中的数据全部恢复,更新内存标识
offlineStorageManager.setOffline(false);
}catch (Exception e){
logger.error("error",e);
}
}
9、责任链模式
public class ChainPatternDemo {
public static void main(String[] args) {
HandlerFactory factory = new HandlerFactory();
Handler handlerChain = factory.getHandlerChain();
handlerChain.execute();
}
}
class HandlerFactory {
Handler firstHandler;
public Handler getHandlerChain(){
buildHandlerChain();
return firstHandler;
}
private void buildHandlerChain(){
Handler thirdHandler = new ProcessResult(null);
Handler secondHandler = new ExecuteTask(thirdHandler);
firstHandler = new ResolveParamter(secondHandler);
}
}
abstract class Handler {
protected Handler successor;
public Handler(Handler successor){
this.successor = successor;
}
abstract void execute();
}
class ResolveParamter extends Handler {
public ResolveParamter(Handler successor) {
super(successor);
}
@Override
void execute() {
System.out.println("解析参数");
if (successor != null){
successor.execute();
}
}
}
class ExecuteTask extends Handler {
public ExecuteTask(Handler successor) {
super(successor);
}
@Override
void execute() {
System.out.println("执行任务");
if (successor != null){
successor.execute();
}
}
}
class ProcessResult extends Handler {
public ProcessResult(Handler successor) {
super(successor);
}
@Override
void execute() {
System.out.println("处理结果");
if (successor != null){
successor.execute();
}
}
}
10、门面模式
Service就是经典的门面模式,融合了很多dao
public class FacadePatternDemo {
public static void main(String[] args) {
/**
* 假设是子系统2
*/
SystemFacade facade = new SystemFacade();
facade.execute();
/**
* 好处1:子系统2不需要care太多的模块,只要care一个门面类的接口就可以了
* 好处2:如果多个地方都要调用这段逻辑,那么如果这个逻辑变了,只需要在门面类一个地方修改就可以了
*/
}
/**
* 子系统1的门面类
*/
public static class SystemFacade {
public void execute(){
/**
* 子系统,封装了自己的多个模块,ABC,基于自己多个模块的功能,对外统一暴露出去一个功能
*/
ModuleA moduleA = new ModuleA();
ModuleB moduleB = new ModuleB();
ModuleC moduleC = new ModuleC();
moduleA.execute();
moduleB.execute();
moduleC.execute();
System.out.println("新增的一段逻辑");
}
}
public static class ModuleA {
public void execute() {
System.out.println("子系统1的模块A的功能");
}
}
public static class ModuleB {
public void execute() {
System.out.println("子系统1的模块B的功能");
}
}
public static class ModuleC {
public void execute() {
System.out.println("子系统1的模块C的功能");
}
}
}
11、装饰模式
对方法的增强
public class DecoratorPatternDemo {
public static void main(String[] args) {
ConcreteComponent concreteComponent = new ConcreteComponent();
Decorator decorator = new Decorator(concreteComponent);
decorator.execute();
}
}
interface Component {
void execute();
}
class ConcreteComponent implements Component {
@Override
public void execute() {
System.out.println("执行基础功能");
}
}
class Decorator implements Component {
private Component component;
public Decorator(Component component){
this.component = component;
}
@Override
public void execute() {
System.out.println("在执行基础功能之前,执行部分功能增强");
component.execute();
System.out.println("在执行基础功能之后,执行部分功能增强");
}
}
12、适配器
public class AdapterPatterDemo {
public static void main(String[] args) {
NewInterface oldObject = new NewInterfaceAdapter(new OldInterfaceImpl());
oldObject.newExecute();
NewInterface newOjbect = new NewInterfaceImpl();
newOjbect.newExecute();
/**
* 适配器
* 就是你手上有新老两个接口和一个老接口的实现类
* 但是现在系统中药面向新接口来开发,老接口的实现类就不能直接用了,不能直接面向老接口来开发
* 开发一个老接口到新接口的一个适配器
* 适配器是实现了新接口的,但是适配器中持有老接口实现类实例的引用
* 适配器的新接口方法的实现,全部基于老接口实现类的老方法来实现即可
* 对于调用方而言,只要使用适配器开发即可,就可以通过面向新接口开发,底层使用老接口实现类
*/
}
/**
* 定义一个适配器
*/
public static class NewInterfaceAdapter implements NewInterface{
private OldInterface oldObject;
public NewInterfaceAdapter(OldInterface oldObject){
this.oldObject = oldObject;
}
@Override
public void newExecute() {
oldObject.oldExecute();
}
}
/**
* 老版本接口
*/
public static interface OldInterface{
void oldExecute();
}
public static class OldInterfaceImpl implements OldInterface{
@Override
public void oldExecute() {
System.out.println("老版本接口实现的功能逻辑");
}
}
/**
* 新版版接口
*/
public static interface NewInterface{
void newExecute();
}
public static class NewInterfaceImpl implements NewInterface{
@Override
public void newExecute() {
System.out.println("新版本接口实现的功能逻辑");
}
}
}
Java IO
String SEPARATOR = File.separator;
File file = new File("e:" + SEPARATOR + "io" + SEPARATOR + "test.txt");
//BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
// 备注上面这个初始化过程就是多次使用包装来完成的,不推荐这么写,会让新手看不懂。
//1、获得子节输入流
FileInputStream fileInputStream=new FileInputStream(file);
//2、构造转换流(是继承Reader的)
InputStreamReader inputStreamReader=new InputStreamReader(fileInputStream);
//3、 构造缓冲字符流
BufferedReader bufferedReader=new BufferedReader(inputStreamReader);
/**
* 备注1、2两步骤体现出了适配器模式
* 由于InputStream是字节流不能享受到字符流读取字符那么便捷的功能,因此借助
* InputStreamReader将其转为Reader子类,因此可以拥有便捷操作文本文件方法。
*/
/**
* 2、3两步骤体现了装饰模式(wrapper包装模式)
* 将InputStream字节流包装为BufferedReader过程就装饰的过程。一开始
* InputStream只有read一个字节的方法,包装为Reader之后拥有read一个字符的功
* 能,在包装成BufferedReader之后就拥有read一行字符串功能
*/
13、原型模式
public <T> T clone(Class<T> clazz) throws Exception{
T target = clazz.newInstance();
BeanCopierUtils.copyProperties(this,target);
return target;
}
BeanCopierUtils 是cglib的一个工具对于类之间的clone
14、享元模式
比如说Worker将返回值返回给Master之后,Master使用Map进行保存,然后对于Master基于任务的状态的判断,走的是这个Map,如果缓存中有则走缓存,没有则走数据库
15、代理模式
JDK
public class JDKProxyDemo {
public static void main(String[] args) throws Exception {
JDKProxy proxy = new JDKProxy();
IUserManager userManager = (IUserManager)proxy.bind(new UserManagerImpl());
userManager.addUser("zhagnsan","123");
}
}
interface IUserManager {
void addUser(String id, String password);
}
class UserManagerImpl implements IUserManager {
@Override
public void addUser(String id, String password) {
System.out.println("======调用了UserManagerImpl.addUser()方法======");
}
}
class JDKProxy implements InvocationHandler {
private Object target;
public Object bind(Object target){
this.target = target;
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
this.target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(this.target,args);
return result;
}
}
CGLIB
/**
* CGLibProxy动态代理类
*/
public class CGLibProxy implements MethodInterceptor {
/** CGLib需要代理的目标对象 */
private Object targetObject;
public Object createProxyObject(Object obj) {
this.targetObject = obj;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
enhancer.setCallback(this);
Object proxyObj = enhancer.create();
// 返回代理对象
return proxyObj;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object obj = method.invoke(targetObject, args);
return obj;
}
}
Dubbo客户端动态代理
public class NettyClient {
private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static NettyClientHandler clientHandler;
//TODO 在这里实现了动态代理模式
public Object getBean(final Class<?> serviceClass,final String provideName) {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[]{serviceClass},(proxy, method, args) -> {
if (clientHandler == null) {
//TODO 在这里初始化netty客户度,初始化的时候已经和server建立的连接,有了上下文
initClient();
}
//TODO 初始化完毕之后给客户度设置参数,HelloService#hello#你好
clientHandler.setParam(provideName + args[0]);
//TODO 通过线程池对任务进行提交,因为NettyClientHandler实现了Callable接口,所以可以直接进行任务的提交
return executorService.submit(clientHandler).get();
});
}
private static void initClient() {
clientHandler = new NettyClientHandler();
EventLoopGroup group = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(clientHandler);
}
});
try {
bootstrap.connect("127.0.0.1",7777).sync();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable {
private ChannelHandlerContext context;
private String result;
private String param;
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
context = ctx;
}
@Override
public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//TODO 在这里等待结果返回
result = msg.toString();
notify();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
}
@Override
public synchronized Object call() throws Exception {
//TODO 这里将数据写了出去
context.writeAndFlush(param);
wait();
return result;
}
void setParam(String param) {
this.param = param;
}
}
动态代理
public class Demo {
public static void main(String[] args) throws Exception {
JdkHandler jdkHandler = new JdkHandler();
User bookApi = (User)jdkHandler.bind(User.class);
bookApi.say("qiaozhanwei");
bookApi.say("qiaozhanwei",30);
}
}
interface User {
void say(String name);
void say(String name,int age);
}
class JdkHandler implements InvocationHandler {
public Object bind(Class<?> serviceClass) {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class<?>[]{serviceClass},this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for (Object object : args) {
System.out.println(object);
}
System.out.println(method.getName());
return null;
}
}
总结
1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,并覆盖其中方法实现增强,但是因为采用的是继承,所以该类或方法最好不要声明成final
如感兴趣,点赞加关注,谢谢
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。