java的设计模式

Java设计模式

策略模式

  1. 声明一个接口用于描述要进行的操作
package com.hg.strategy;

public interface Operation {
    public int doOperation(int num1, int num2);
}
  1. 声明一个类,调用接口的方法进行操作
package com.hg.strategy;

public class Caculator {
    private Operation operation;

    public void setOperation(Operation operation) {
        this.operation = operation;
    }

    public int doOperation(int num1, int num2){
        return this.operation.doOperation(num1, num2);
    }
}
  1. 声明接口的实现类
package com.hg.strategy;

public class OperationAdd implements Operation{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 + num2;
    }
}
package com.hg.strategy;

public class OperationSub implements Operation{
    @Override
    public int doOperation(int num1, int num2) {
        return num1 - num2;
    }
}
  1. 测试
package com.hg.strategy;

public class Test {
    public static void main(String[] args) {
        Caculator caculator = new Caculator();
        Operation operation = new OperationAdd();
        caculator.setOperation(operation);
        System.out.println(caculator.doOperation(1, 2));
    }
}

策略模式的好处是如果将接口生成一个jar包,引用这个jar包后,直接实现这个接口的方法就可以实现代码的扩展性,实现关闭修改,打开扩展的原则

装饰模式

装饰模式有两个重要的属性:装饰器,被装饰的对象,装饰器和被装饰的对象要实现同一个接口,装饰器中要使用被装饰的对象。

  1. 创建共同接口
package com.hg.decorator;

public interface Person {
    public Double cost();
    public void show();
}
  1. 创建被装饰对象,实现Person接口
package com.hg.decorator;

public class XiaoMing implements Person{
    @Override
    public Double cost() {
        return 0.0;
    }

    @Override
    public void show() {
        System.out.println("没穿衣服的小明");
    }
}
  1. 创建装饰器,实现Person接口
package com.hg.decorator;

public abstract class ClothingDecorator implements Person{
    protected Person person;

    public ClothingDecorator(Person person) {
        this.person = person;
    }
}
  1. 创建装饰器的子类,实现操作
package com.hg.decorator;

public class ShirtDecorator extends ClothingDecorator{
    public ShirtDecorator(Person person) {
        super(person);
    }

    @Override
    public Double cost() {
        return person.cost() + 1000;
    }

    @Override
    public void show() {
        this.person.show();
        System.out.println("购买一件衬衫,花费:" + this.cost());
    }
}
package com.hg.decorator;

public class TrouserDecorator extends ClothingDecorator{
    public TrouserDecorator(Person person) {
        super(person);
    }

    @Override
    public Double cost() {
        return this.person.cost() + 800;
    }

    @Override
    public void show() {
        System.out.println("购买了一条裤子,累计花费:" + this.cost());
    }
}
  1. 测试类
package com.hg.decorator;

public class Test {
    public static void main(String[] args) {
        Person xiaoming = new XiaoMing();
        xiaoming = new ShirtDecorator(xiaoming);
        xiaoming.show();
        System.out.println("共计花费:" + xiaoming.cost());
        xiaoming = new TrouserDecorator(xiaoming);
        xiaoming.show();
        System.out.println("共计花费:" + xiaoming.cost());
    }
}

xiaoming = new ShirtDecorator(xiaoming);为什么ShirtDecorator类的对象可以赋值给XiaoMing类的对象,因为这两个类都实现了Person接口,所以可以互相赋值。

装饰模式通过扩充装饰器的子类,可以实现程序的扩展。

观察者模式

观察者模式定义了对象的一对多依赖关系,当“一”的状态发生改变,所有依赖也随之发生改变。观察者模式也称为发布模式。观察者模式有两个角色,观察者和被观察者,当被观察者模式发生改变时,观察者模式随之改变。具体实现方法为:被观察者保存一份观察者的列表,当被观察者状态改变时,会通知观察者进行更新。

观察者

package com.hg.observer;

//观察者
public abstract class Customer {
    public abstract void update();
}
package com.hg.observer;

//观察者扩展类A
public class CustomerA extends Customer{
    @Override
    public void update() {
        System.out.println("客户A报纸已送达");
    }
}
package com.hg.observer;

//观察者扩展类B
public class CustomerB extends Customer{
    @Override
    public void update() {
        System.out.println("客户B报纸已送达");
    }
}

被观察者

package com.hg.observer;

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

//被观察者
public class NewsPaperOffice {
    private List<Customer> customers = new ArrayList<>();
    //将观察者添加到列表
    public void addCustomers(Customer customer){
        this.customers.add(customer);
    }
    //遍历所有观察者
    public void notifyAllCustomers(){
        for (Customer customer : this.customers) {
            customer.update();
        }
    }
    //状态改变,对观察者进行通知
    public void newspaper(){
        this.notifyAllCustomers();
    }
}

测试程序

package com.hg.observer;

public class Test {
    public static void main(String[] args) {
        NewsPaperOffice newsPaperOffice = new NewsPaperOffice();
        Customer customerA = new CustomerA();
        Customer customerB = new CustomerB();
        newsPaperOffice.addCustomers(customerA);
        newsPaperOffice.addCustomers(customerB);
        newsPaperOffice.newspaper();
    }
}

单例模式

单线程下的单例模式

package com.hg.single;

public class Single {
    private static Single instance;
    private Single(){
        System.out.println("创建了Single对象");
    }
    public static Single getInstance(){
        if (instance == null) instance = new Single();
        return instance;
    }
}
package com.hg.single;

public class Test {
    public static void main(String[] args) {
        for (int i = 0; i < 9; i++) {
            Single single = Single.getInstance();
        }
    }
}

多线程下的单例模式

使用单线程模式下的单例模式开发,在多线程模式下,因各个线程抢占资源,所以导致getInstace()方法还未进行判断就被多个线程调用,无法实现单例模式,需要给getInstace()方法添加synchronized关键字,给线程上锁。

package com.hg.single;

public class Single {
    private static Single instance;
    private Single(){
        System.out.println("创建了Single对象");
    }
    public static synchronized Single getInstance(){
        if (instance == null) instance = new Single();
        return instance;
    }
}

使用直接给方法加锁的方式会造成每个线程运行getInstace()方法都会等待,造成资源浪费。

可以在声明instance时直接进行实例化,就不用加锁了。

package com.hg.single;

public class Single {
    private static Single instance = new Single();
    private Single(){
        System.out.println("创建了Single对象");
    }
    public static Single getInstance(){
        if (instance == null) instance = new Single();
        return instance;
    }
}

还可以进行双重检测,进行判断

package com.hg.single;

public class Single {
    private volatile static Single instance;
    private Single(){
        System.out.println("创建了Single对象");
    }
    public static Single getInstance(){
        if (instance == null){
            synchronized (Single.class){
                if (instance == null) instance = new Single();
            }
        }
        return instance;
    }
}

工厂模式

工厂模式在开发时不需要手动创建对象,创建对象的工作全部交由工厂类去完成,需要对象时,直接从工厂了调用相应的方法即可完成对象的创建。

创建接口

package com.hg.factory;

public interface Computer {
}

创建实现类

package com.hg.factory;

public class ComputerA implements Computer{
}
package com.hg.factory;

public class ComputerB implements Computer{
}

创建工厂类

package com.hg.factory;

public class ComputerFactory {
    public Computer createComputer(String name){
        Computer computer = null;
        if (name == "a"){
            computer = new ComputerA();
        }
        if (name == "b"){
            computer = new ComputerB();
        }
        return computer;

    }
}

测试类

package com.hg.factory;

public class Test {
    public static void main(String[] args) {
        ComputerFactory computerFactory = new ComputerFactory();
        computerFactory.createComputer("a");
        computerFactory.createComputer("b");
    }
}

适配器模式

将一个接口转换为用户希望的另一个接口,解决类之间接口不兼容的问题,相当于电源的接口转换器,将两项插头转为三项插头。

创建一个播放类,播放不同格式的音乐文件

package com.hg.adapter;

public class MyPlayer {
    public void playMp3(String filename){
        System.out.println("play mp3:" + filename);
    }
    public void playWma(String filename){
        System.out.println("play Wma" + filename);
    }
}

创建一个播放器接口

package com.hg.adapter;

public interface MusicPlayer {
    public void play(String type,String filename);
}

创建适配器,识别不同的音乐格式,播放音乐

package com.hg.adapter;

public class MusicAdapter implements MusicPlayer{
    private MyPlayer myPlayer;

    public MusicAdapter() {
        this.myPlayer = new MyPlayer();
    }

    @Override
    public void play(String type, String filename) {
        if (type == "mp3") this.myPlayer.playMp3(filename);
        if(type =="wma") this.myPlayer.playWma(filename);
    }
}

测试

package com.hg.adapter;

public class Test {
    public static void main(String[] args) {
        MusicPlayer musicPlayer = new MusicAdapter();
        musicPlayer.play("mp3","Break My Heart");
        musicPlayer.play("wma","Bye Bye Bye");
    }
}

代理模式

spring的aop就是通过代理模式来实现的,通过代理模式可以实现目标对象和业务方法的解耦合。

业务类要和代理类实现同一个接口

接口

package com.hg.proxy;

public interface House {
    public void findHouse();
}

业务类(实现接口)

package com.hg.proxy;

public class XiaoMing implements House{
    @Override
    public void findHouse() {
        System.out.println("找房子");
    }
}

代理类(和业务类实现同一个接口)

package com.hg.proxy;

public class HouseProxy implements House{

    private House house;

    public HouseProxy(House house) {
        this.house = house;
    }

    @Override
    public void findHouse() {
        //执行业务代码前,进行一些其他业务,如打印日志
        System.out.println("日志:找了一个代理");
        this.house.findHouse();
    }
}

如何使用

package com.hg.proxy;

public class Test {
    public static void main(String[] args) {
        House house = new XiaoMing();
        HouseProxy houseProxy = new HouseProxy(house);
        houseProxy.findHouse();
    }
}

模板方法模式

将不同类中相同的业务方法提取出来,封装到一个父类中的模式称为模板方法模式。子类可以将父类中的方法拿来直接使用,同时也可以修改继承的方法增加扩展业务。这种模式即保障了代码的复用性,又增加了代码的灵活性。

设计思路

已做饭为例子,开油烟机、生火、关火、关油烟机等操作是固定不变的,把这些操作放到一个模板类中

模板类

package com.hg.templatemethod;

public abstract class Cook {
    public void open(){
        System.out.println("打开油烟机");
    }
    public void fire(){
        System.out.println("开火");
    }
    //不同的菜肴有不同的制作方法
    public abstract void doCook();

    public void outFire(){
        System.out.println("关火");
    }
    public void close(){
        System.out.println("关闭油烟机");
    }
    public void cook(){
        open();
        fire();
        doCook();
        outFire();
        close();
    }
}

炒西红柿类

package com.hg.templatemethod;

public class CookTomato extends Cook{
    @Override
    public void doCook() {
        System.out.println("炒西红柿");
    }
}

炒土豆类

package com.hg.templatemethod;

public class CookPotato extends Cook{
    @Override
    public void doCook() {
        System.out.println("炒土豆丝");
    }
}

测试类

package com.hg.templatemethod;

public class Test {
    public static void main(String[] args) {
        Cook cook = new CookTomato();
        cook.cook();
        System.out.println("******************************");
        cook = new CookPotato();
        cook.cook();
    }
}

实践-模拟servlet的使用

Servlet就是一种模板模式,我们可以模拟实现Servlet继承关系来实践模板方法模式的开发

  1. 创建一个类实现servlet接口
package com.hg.templatemethod.servlet;

import javax.servlet.*;
import java.io.IOException;

public class MyGenericServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

其中需要操作的方法只有service方法,需要再实现一个类,将service方法单独提取出来

  1. 提取service方法,并根据不同的请求进行拆分
package com.hg.templatemethod.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class MyHttpServlet extends MyGenericServlet {
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        switch (request.getMethod()) {
            case "GET":
                doGet(request, response);
                break;
            case "POST":
                doPost(request, response);
                break;
        }
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) {

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) {

    }
}
  1. 创建自己的sevlet
package com.hg.templatemethod.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class MyServlet extends MyHttpServlet {
    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response) {
        
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response) {
        
    }
}

责任链模式

是对请求的一种链式调用,所谓责任就是对请求的某些操作(如去除广告,游戏推广等)。具体实现是为某一个请求创建一个对象链,每个对象都会依次检查这个请求,并进行一些处理。

实践:模拟论坛对用户发的贴子进行过滤

信息对象

package com.hg.reponsibility;

//请求内容
public class Post {
    //请求内容
    private String content;

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
    
}

处理器父类(每一个处理器都会包含链中的下一个处理器)

package com.hg.reponsibility;

public abstract class PostHandler {
    //下一个处理器
    private PostHandler handler;

    public void setHandler(PostHandler handler) {
        this.handler = handler;
    }

    //对请求的处理函数
    public abstract void handlerRequest(Post post);

    //将处理后的请求传递给下一个对象
    public void next(Post post){
        //如果有下一个处理器,就继续进行处理
        if (this.handler != null){
            this.handler.handlerRequest(post);
        }else{
            System.out.println("没有下一个处理器了");
        }
    }
}

处理器A

package com.hg.reponsibility;

public class AHandler extends PostHandler{
    @Override
    public void handlerRequest(Post post) {
        //对post内容进行处理
        String content = post.getContent();
        content = content.replace("广告", "**");
        post.setContent(content);
        System.out.println("过滤广告");
        //继续进行下一个处理
        next(post);
    }
}

处理器2

package com.hg.reponsibility;

public class BHandler extends PostHandler {
    @Override
    public void handlerRequest(Post post) {
        String content = post.getContent();
        content = content.replace("游戏推广", "****");
        post.setContent(content);
        System.out.println("过滤游戏推广");
        next(post);
    }
}

测试程序

package com.hg.reponsibility;

public class Test {
    public static void main(String[] args) {
        Post post = new Post();
        post.setContent("正常内容,广告,游戏推广");
        PostHandler postHandlerA = new AHandler();
        PostHandler postHandlerB = new BHandler();
        postHandlerA.setHandler(postHandlerB);
        System.out.println("处理前的请求内容" + post.getContent());
        postHandlerA.handlerRequest(post);
        System.out.println("处理后的请求内容" + post.getContent());
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值