三、程序员进阶之道--设计模式

版权声明:话不在多,在于精 https://blog.csdn.net/qq_29857681/article/details/90168976

访问者模式

精髓之处: 在不改变内部元素对象的基础上,实现不同的访问者拥有不同的操作。

示例:划价人员拿到处方单之后根据药品名称和数量计算总价,而药房工作人员根据药品名称和数量准备药品

这里的处方单就是那个复杂对象,内部的处方项就是内部元素对象

划价人员和药房人员是两个不同的访问者。

代码实现:

package com.jd.testjava.testdesignpattern.visitor3;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

interface Element {
    void accept(IVisitor visitor);

    void doSomething();
}

class ConcreteElement1 implements Element {
    @Override
    public void doSomething() {
        System.out.println("这是元素1");
    }

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

class ConcreteElement2 implements Element {
    @Override
    public void doSomething() {
        System.out.println("这是元素2");
    }

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

class ConcreteElement3 implements Element {
    @Override
    public void doSomething() {
        System.out.println("这是元素3");
    }

    @Override
    public void accept(IVisitor visitor) {
        visitor.visit(this);
    }
}

interface IVisitor {
    void visit(ConcreteElement1 el1);

    void visit(ConcreteElement2 el2);

    void visit(ConcreteElement3 el3);
}

class Visitor implements IVisitor {
    @Override
    public void visit(ConcreteElement1 el1) {
        el1.doSomething();
    }

    @Override
    public void visit(ConcreteElement2 el2) {
        el2.doSomething();
    }

    @Override
    public void visit(ConcreteElement3 el3) {
        el3.doSomething();
    }
}

class ObjectStruture {
    public static List<Element> getList() {
        List<Element> list = new ArrayList<Element>();
        Random ran = new Random();
        for (int i = 0; i < 10; i++) {
            int a = ran.nextInt(100);
            if (a > 50) {
                list.add(new ConcreteElement1());
            } else {
                list.add(new ConcreteElement3());
            }
        }
        return list;
    }
}

public class Client {
    public static void main(String[] args) {
        List<Element> list = ObjectStruture.getList();
        for (Element e : list) {
            e.accept(new Visitor());
        }
    }
}

模板模式

精髓:父类控制行为,子类进行实现

示例: 玩游戏时,游戏的整个流程都已经规划好,所有游戏都是按照这个流程,具体这个流程做什么事 由各种实际游戏进行实现

package com.jd.testjava.testdesignpattern;

/**
 * 模板模式
 * @author lichenyang8
 * @date 2019/5/15
 */
public class TestTemplatePattern {
    public static void main(String[] args) {

        Game game = new Cricket();
        game.play();
        System.out.println();
        game = new Football();
        game.play();
    }
}

abstract class Game {
    abstract void initialize();
    abstract void startPlay();
    abstract void endPlay();

    //模板方法 final不能改变
    public final void play(){

        //初始化游戏
        initialize();

        //开始游戏
        startPlay();

        //结束游戏
        endPlay();
    }
}
class Cricket extends Game {

    @Override
    void endPlay() {
        System.out.println("Cricket Game Finished!");
    }

    @Override
    void initialize() {
        System.out.println("Cricket Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Cricket Game Started. Enjoy the game!");
    }
}
class Football extends Game {

    @Override
    void endPlay() {
        System.out.println("Football Game Finished!");
    }

    @Override
    void initialize() {
        System.out.println("Football Game Initialized! Start playing.");
    }

    @Override
    void startPlay() {
        System.out.println("Football Game Started. Enjoy the game!");
    }
}

策略模式

精髓:避免使用多重条件判断的复杂性

示例:将一个页面分享到不同的渠道(QQ 微信,朋友圈) 不同的渠道内容不同,此时可以使用策略模式,将不同的渠道设计成不同的策略,不同的策略配置不同的模板内容,行为随着策略对象改变而改变的 context 对象。

package com.jd.testjava.testdesignpattern;

/**
 * @author lichenyang8
 * @date 2019/5/15
 */
public class TestStrategyPattern {
    public static void main(String[] args) throws Exception {
        ShareContext context = ShareContext
                .getShareTarget(1);
        System.out.println(ShareContext.getShareInfo(context));
    }
}

/**
 * 标题
 */
interface ShareTitle {
    String showTitle();
}
//这样在新增分享渠道时 不用修改代码 只需要配置即可
/*配置文件
share.wechat.title=这个APP竟然这么棒
share.wechat.content=还不快来加入我们旅游派对
share.wechat.link.android=https://www.666.com/salesman/shareRegister?android&userToken=
share.wechat.link.ios=https://www.666.com/salesman/shareRegister?ios&userToken=
share.wechat.image.url.android=android wechat img url
share.wechat.image.url.ios=ios wechat img url

1=com.nicky.facade.sharestrategy.targets.QQShare
*/

/**
 * 微信标题
 */
class WechatTitle implements ShareTitle {

    @Override
    public String showTitle() {
        return BundleUtil.getResult("share.wechat.title");
    }
}

class ShareContext {

    protected ShareTitle shareTitle;


    public static ShareContext getShareTarget(Integer type) {
        //从配置文件中加载
        String className = BundleUtil.getResult(type.toString());
        Class cls;
        try {
            cls = Class.forName(className);
            return (ShareContext) cls.newInstance();
        } catch (ReflectiveOperationException e) {
            e.printStackTrace();
        }
        return null;
    }

    public final String showTitle() {
        return shareTitle.showTitle();
    }

    /**
     * 传入不同的context类 可以得到不同的分享内容
     * @param context
     * @param platform
     * @param userToken
     * @return
     */
    public static ShareInfo getShareInfo(ShareContext context, String platform, String userToken) {
        ShareInfo info = new ShareInfo();
        info.setTitle(context.showTitle());
        return info;
    }
}

/**
 * 微信分享
 */
class WechatShare extends ShareContext {
    public WechatShare() {
        super.shareTitle = new WechatTitle();
    }
}

观察者模式

精髓: 建立一套触发机制,一方有改变,多方立马知道

典型的发布-订阅模式

示例: 微信公众号,关注后就会有文章推送

package com.jd.testjava.testdesignpattern;

import java.util.ArrayList;
import java.util.List;

/**
 * @author lichenyang8
 * @date 2019/5/16
 */
public class TestObserverPattern {
    public static void main(String[] args) {
        WechatServer server = new WechatServer();

        Observer userZhang = new User("ZhangSan");
        Observer userLi = new User("LiSi");
        Observer userWang = new User("WangWu");

        server.registerObserver(userZhang);
        server.registerObserver(userLi);
        server.registerObserver(userWang);
        server.setInfomation("PHP是世界上最好用的语言!");

        System.out.println("----------------------------------------------");
        server.removeObserver(userZhang);
        server.setInfomation("JAVA是世界上最好用的语言!");

    }
}

interface Observerable {

    public void registerObserver(Observer o);
    public void removeObserver(Observer o);
    public void notifyObserver();

}

interface Observer {
    public void update(String message);
}

class WechatServer implements Observerable {

    //注意到这个List集合的泛型参数为Observer接口,设计原则:面向接口编程而不是面向实现编程
    private List<Observer> list;
    private String message;

    public WechatServer() {
        list = new ArrayList<Observer>();
    }

    @Override
    public void registerObserver(Observer o) {

        list.add(o);
    }

    @Override
    public void removeObserver(Observer o) {
        if(!list.isEmpty())
            list.remove(o);
    }

    //遍历
    @Override
    public void notifyObserver() {
        for(int i = 0; i < list.size(); i++) {
            Observer oserver = list.get(i);
            oserver.update(message);
        }
    }

    public void setInfomation(String s) {
        this.message = s;
        System.out.println("微信服务更新消息: " + s);
        //消息更新,通知所有观察者
        notifyObserver();
    }

}
class User implements Observer {

    private String name;
    private String message;

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

    @Override
    public void update(String message) {
        this.message = message;
        read();
    }

    public void read() {
        System.out.println(name + " 收到推送消息: " + message);
    }

}

命令模式

精髓: 通过命令类对请求发送者与请求处理者进行解耦和,发送者发送命令,在命令内部调用处理者处理请求

示例: 电视遥控器,遥控发送命令,电视机接收命令,内部调用处理者处理命令

package com.jd.testjava.testdesignpattern;

/**
 * @author lichenyang8
 * @date 2019/5/17
 */
public class TestCommandPattern {
    public static void main(String[] args) {
        // 命令接收者Receiver
        Tv myTv = new Tv();
        // 开机命令ConcreteCommond
        CommandOn on = new CommandOn(myTv);
        // 命令控制对象Invoker
        Control control = new Control(on);
        // 开机
        control.turnOn();

    }

}

interface Command {
    void execute();
}

class Tv {
    public int currentChannel = 0;

    public void turnOn() {
        System.out.println("The televisino is on.");
    }

    public void turnOff() {
        System.out.println("The television is off.");
    }


    public void changeChannel(int channel) {
        this.currentChannel = channel;
        System.out.println("Now TV channel is " + channel);
    }
}

class CommandOn implements Command {

    private Tv myTv;


    public CommandOn(Tv tv) {
        myTv = tv;
    }


    @Override
    public void execute() {
        myTv.turnOn();
    }
}

class Control {
    private Command onCommand;


    public Control(Command on) {
        onCommand = on;
    }


    public void turnOn() {
        onCommand.execute();
    }


}

责任链模式

精髓:以链式结构对请求的发送者和接收者进行解耦

示例: Struts2的请求处理

package com.jd.testjava.testdesignpattern;

import java.util.ArrayList;
import java.util.List;

/**
 * 处理连(责任链)
 *
 * @author lichenyang8
 * @date 2019/5/20
 */
public class TestHanderChain {
    public static void main(String args[]) {
        //设定过滤规则,对msg字符串进行过滤处理
        String msg = ":):,<script>,敏感,被就业,网络授课";
        //过滤请求
        Request request=new Request();
        //set方法,将待处理字符串传递进去
        request.setRequest(msg);
        //处理过程结束,给出的响应
        Response response=new Response();
        //设置响应信息
        response.setResponse("response:");
        //FilterChain,过滤规则形成的拦截链条
        FilterChain fc=new FilterChain();
        //规则链条添加过滤规则,采用的是链式调用
        fc.addFilter(new HTMLFilter())
                .addFilter(new SensitiveFilter())
                .addFilter(new FaceFilter());
        //按照FilterChain的规则顺序,依次应用过滤规则
        fc.doFilter(request, response,fc);
        //打印请求信息
        System.out.println(request.getRequest());
        //打印响应信息
        System.out.println(response.getResponse());
        /*
         * 处理器对数据进行处理
         * --|----|---数据--|-----|---
         * 规则1      规则2                 规则3       规则4
         */
    }

}

class Request {
    String requestStr;

    public String getRequest() {
        return requestStr;
    }

    public void setRequest(String request) {
        this.requestStr = request;
    }

}
class Response {
    String responseStr;

    public String getResponse() {
        return responseStr;
    }

    public void setResponse(String response) {
        this.responseStr = response;
    }

}
/*
 * 定义接口Filter,具体的过滤规则需要实现这个接口,最后一个参数添加的意义是我们在Main函数中:
 * fc.doFilter(request, response,fc);执行这一步的时候可以按照规则链条一次使用三个过滤规则对字符串进行处理
 * 因为
 *
 */
interface Filter {
    void doFilter(Request request,Response response,FilterChain chain);
}
class HTMLFilter implements Filter {

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        //将字符串中出现的"<>"符号替换成"[]"
        request.requestStr=request.requestStr
                .replace('<', '[').replace('>', ']')+
                //后面添加的是便于我们观察代码执行步骤的字符串
                "----HTMLFilter()";
        chain.doFilter(request, response,chain);
        response.responseStr+="---HTMLFilter()";
    }

}
class SensitiveFilter implements Filter{

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {
        //处理字符串中的敏感信息,将被就业和谐成就业
        request.requestStr=request.requestStr
                .replace("被就业", "就业").replace("敏感", "")+
                //后面添加的是便于我们观察代码执行步骤的字符串
                " ---sensitiveFilter()";
        chain.doFilter(request, response,chain);
        response.responseStr+="---sensitiveFilter()";
    }

}
class FaceFilter implements Filter {

    @Override
    public void doFilter(Request request, Response response, FilterChain chain) {

        //将字符串中出现的":):"转换成"^V^";
        request.requestStr = request.requestStr.replace(":):", "^V^")
                //后面添加的是便于我们观察代码执行步骤的字符串
                + "----FaceFilter()";
        chain.doFilter(request, response, chain);
        response.responseStr += "---FaceFilter()";
    }

}
class FilterChain implements Filter{
    //用List集合来存储过滤规则
    List<Filter> filters = new ArrayList<Filter>();
    //用于标记规则的引用顺序
    int index=0;
    //往规则链条中添加规则
    public FilterChain addFilter(Filter f) {
        filters.add(f);
        //代码的设计技巧:Chain链添加过滤规则结束后返回添加后的Chain,方便我们下面doFilter函数的操作
        return this;
    }
    @Override
    public void doFilter(Request request, Response response, FilterChain chain){
        //index初始化为0,filters.size()为3,不会执行return操作
        if(index==filters.size()){
            return;
        }
        //每添加一个过滤规则,index自增1
        Filter f=filters.get(index);
        index++;
        //根据索引值获取对应的规律规则对字符串进行处理
        f.doFilter(request, response, chain);
    }
}

代理模式

精髓:在不改变目标类的前提下,无侵入地添加新的功能

示例:jdk的动态代理

package com.jd.testjava.testdesignpattern;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author lichenyang8
 * @date 2019/5/20
 */
public class TestProxyPattern {
    public static void main(String[] args) {
        //真实对象
        Subject realSubject =  new RealSubject();

        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(realSubject);
        //代理对象
        Subject proxyClass = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Subject.class}, myInvocationHandler);

        proxyClass.sellBooks();

        proxyClass.speak();
    }
}

interface Subject {
    public int sellBooks();

    public String speak();
}
class RealSubject implements Subject{
    @Override
    public int sellBooks() {
        System.out.println("卖书");
        return 1 ;
    }

    @Override
    public String speak() {
        System.out.println("说话");
        return "张三";
    }
}
class MyInvocationHandler implements InvocationHandler {
    /**
     * 因为需要处理真实角色,所以要把真实角色传进来
     */
    Subject realSubject ;

    public MyInvocationHandler(Subject realSubject) {
        this.realSubject = realSubject;
    }

    /**
     *
     * @param proxy    代理类
     * @param method    正在调用的方法
     * @param args      方法的参数
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用代理类");
        if(method.getName().equals("sellBooks")){
            int invoke = (int)method.invoke(realSubject, args);
            System.out.println("调用的是卖书的方法");
            return invoke ;
        }else {
            String string = (String) method.invoke(realSubject,args) ;
            System.out.println("调用的是说话的方法");
            return  string ;
        }
    }
}

装饰器模式

精髓:装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。是对现有类的包装

示例:Java io中 BufferedOutputStream 和 FileOutputStream

package com.jd.testjava.testdesignpattern;

/**
 * @author lichenyang8
 * @date 2019/5/21
 */
public class TestDecoratorPattern {
    public static void main(String[] args) {

        Shape circle = new Circle();
        ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
        ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
        //Shape redCircle = new RedShapeDecorator(new Circle());
        //Shape redRectangle = new RedShapeDecorator(new Rectangle());
        System.out.println("Circle with normal border");
        circle.draw();

        System.out.println("\nCircle of red border");
        redCircle.draw();

        System.out.println("\nRectangle of red border");
        redRectangle.draw();
    }
}

abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

    public ShapeDecorator(Shape decoratedShape){
        this.decoratedShape = decoratedShape;
    }

    public void draw(){
        decoratedShape.draw();
    }
}

class RedShapeDecorator extends ShapeDecorator {

    public RedShapeDecorator(Shape decoratedShape) {
        super(decoratedShape);
    }

    @Override
    public void draw() {
        decoratedShape.draw();
        setRedBorder(decoratedShape);
    }

    private void setRedBorder(Shape decoratedShape){
        System.out.println("Border Color: Red");
    }
}
interface Shape {
    void draw();
}
class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("Shape: Rectangle");
    }
}
class Circle implements Shape {

    @Override
    public void draw() {
        System.out.println("Shape: Circle");
    }
}

适配器模式

精髓:有两种

1. (接口适配器)想要使用一个接口,但是必须实现接口所有的方法,这时就可以使用抽象适配器对接口方法进行空实现,然后通过自己的类继承抽象适配器,覆盖自己想要的方法即可。

2.  (类适配器)存在于不匹配的二者之间,用于连接二者,将不匹配变得匹配

示例: HttpServletRequestWrapper 

接口适配器:

package com.jd.testjava.testdesignpattern;

/**
 * @author lichenyang8
 * @date 2019/5/21
 */
public class TestAdapterPattern {
    public static void main(String[] args) {
        A a = new Ashili();
        a.a();
        a.d();
    }
}
interface A {
    void a();
    void b();
    void c();
    void d();
    void e();
    void f();
}
abstract class Adapter implements A {
    public void a(){}
    public void b(){}
    public void c(){}
    public void d(){}
    public void e(){}
    public void f(){}
}
class Ashili extends Adapter {
    public void a(){
        System.out.println("实现A方法被调用");
    }
    public void d(){
        System.out.println("实现d方法被调用");
    }
}

类适配器

package com.jd.testjava.testdesignpattern;

/**
 * @author lichenyang8
 * @date 2019/5/21
 */
public class TestAdapterPattern {
    public static void main(String[] args) {
        Ps2 p = new Adapter(new Usber());
        p.isPs2();
    }

}

interface Ps2 {
    void isPs2();
}

interface Usb {
    void isUsb();
}

class Usber implements Usb {

    @Override
    public void isUsb() {
        System.out.println("USB口");
    }

}

class Adapter implements Ps2 {

    private Usb usb;

    public Adapter(Usb usb) {
        this.usb = usb;
    }

    @Override
    public void isPs2() {
        usb.isUsb();
    }

}

猜你喜欢

转载自blog.csdn.net/qq_29857681/article/details/90168976