关于设计模式:设计模式入门

59次阅读

共计 16953 个字符,预计需要花费 43 分钟才能阅读完成。

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

正文完
 0