java常用设计模式

1.建造者模式

public class BuilderTest {
    public static void main(String[] args) {

        Director director = new Director();
        Human humanByDirector = director.createHumanByDirector(new SmartManBuilder());
        System.out.println(humanByDirector.getHead());
        System.out.println(humanByDirector.getBody());
        System.out.println(humanByDirector.getHand());
        System.out.println(humanByDirector.getFoot());

    }
}

// 人
class Human {

    private String head;
    private String body;
    private String hand;
    private String foot;

    public String getHead() {
        return head;
    }

    public void setHead(String head) {
        this.head = head;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getHand() {
        return hand;
    }

    public void setHand(String hand) {
        this.hand = hand;
    }

    public String getFoot() {
        return foot;
    }

    public void setFoot(String foot) {
        this.foot = foot;
    }
}

// 这个就是人的类了,我们取名为human。只要是人都是这个类出来的。
// 那我们想要造人的话,得有一个标准吧?  来要造人的话得有一个步骤吧?头,身体,手,脚,那都得有。
// 所以我们先写一个接口。一个定义了造人标准的接口
interface IBuildHuman {

    void buildHead();

    void buildBody();

    void buildHand();

    void buildFoot();

    Human createHuman();

}

// createHuman方法给你返回一个我们想要造的人。
// 现在,人的类和造人的标准我们都定义好了。那我们可以先造一个人出来,先造一个高智商的人吧。

class SmartManBuilder implements IBuildHuman {

    Human human;

    public SmartManBuilder() {
        human = new Human();
    }

    @Override
    public void buildHead() {
        human.setHead("智商180的人");
    }

    @Override
    public void buildBody() {

        human.setBody("新的身体");
    }

    @Override
    public void buildHand() {

        human.setHand("新的手");
    }

    @Override
    public void buildFoot() {

        human.setFoot("新的脚");
    }

    @Override
    public Human createHuman() {
        return human;
    }
}
// 就是介绍建造者模式的精髓,那就是director。
// 这个director呢,就是来执行我们刚才的造人动作的。没错,精髓就是我们刚才的造人动作。

class Director {
    public Human createHumanByDirector(IBuildHuman iBuildHuman) {
        iBuildHuman.buildHead();
        iBuildHuman.buildBody();
        iBuildHuman.buildHand();
        iBuildHuman.buildFoot();
        return iBuildHuman.createHuman();
    }
}

2.工厂模式

1.简单工厂模式
import java.math.BigDecimal;

/**
 * @author xiaoxiao
 * @create 2021-07-24 15:08
 */
// 简单工厂模式
public class SimpleFactory {

    public static Car createCar(int number) {
        Car car = null;
        switch (number) {
            case 1:
                car = new Car("日产", new BigDecimal(2000000));
                break;
            case 2:
                car = new Car("国产", new BigDecimal(2000000));
                break;
            default:
                break;
        }
        return car;
    }
}

class Car {

    private String name;
    private BigDecimal price;

    public Car() {

    }

    public Car(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}
2.抽象工厂模式
// 抽象工厂,可扩展
public class AbstractFactoryTest {
    public static void main(String[] args) {
        AFactory aFactory = new AFactory();
        aFactory.createProduct().show();
    }
}


// 产品
abstract class Product {

    abstract void show();

}

class Paper extends Product {

    @Override
    void show() {
        System.out.println("我是产品纸!!!");
    }
}

class Food extends Product {


    @Override
    void show() {
        System.out.println("我是产品食物");
    }
}

// 工厂
abstract class Factory {

    abstract Product createProduct();

}

class AFactory extends Factory {


    @Override
    Product createProduct() {
        return new Food();
    }
}

3.单例模式

1.饿汉式
public class SingleHungry {

    private static final SingleHungry SINGLE_HUNGRY = new SingleHungry();

    private SingleHungry() {}

    public static SingleHungry getInstance() {
        return SINGLE_HUNGRY;
    }
}
2.懒汉式
public class SingleLazy {

    // 线程安全,volatile保证在所有线程同步
    private static volatile SingleLazy singleLazy = null;

    public static synchronized SingleLazy getSingleLazy(){

        if (singleLazy == null){
            singleLazy = new SingleLazy();
        }

        return singleLazy;
    }

}

4.适配器模式

1.类适配器
/**
 * 结构型模式:适配器模式 --- 类适配器
 * Usb接口,Ps2接口,无法直接互相使用,因此通过类适配器的方式,进行适配
 * 文章参考:https://www.cnblogs.com/V1haoge/p/6479118.html
 * 
 * 类适配器与对象适配器的使用场景一致,仅仅是实现手段稍有区别,二者主要用于如下场景:
 * (1)想要使用一个已经存在的类,但是它却不符合现有的接口规范,导致无法直接去访问,这时创建一个适配器就能间接去访问这个类中的方法
 * (2)我们有一个类,想将其设计为可重用的类(可被多处访问),我们可以创建适配器来将这个类来适配其他没有提供合适接口的类
 * 
 * 原文链接:https://blog.csdn.net/weixin_40834464/article/details/82958187
 *
 */
// 有USB标准接口,但是PS2也想插入用一下,直接使用是不行的,因此需要适配器
public class ClassAdapterTest {
    public static void main(String[] args) {

        PS2 ps2 = new USBerAdapter();
        ps2.isPS2();

    }
}

interface USB {
    void isUSB();
}

interface PS2 {
    void isPS2();
}

class USBer implements USB {

    @Override
    public void isUSB() {
        System.out.println("我是USB");
    }
}

// 类适配器
class USBerAdapter extends USBer implements PS2 {

    @Override
    public void isPS2() {
        super.isUSB();
    }

}

// 对象适配器
class USBObjectAdapter implements PS2 {

    private USBer usBer;

    public USBObjectAdapter(USBer usBer) {
        this.usBer = usBer;
    }

    @Override
    public void isPS2() {
        usBer.isUSB();
    }
}
2.接口适配器
/**
 * 接口适配器使用场景:
 *(1)想要使用接口中的某个或某些方法,但是接口中有太多方法,
 *我们要使用时必须实现接口并实现其中的所有方法,可以使用抽象类来实现接口,
 *并不对方法进行实现(仅置空),然后我们再继承这个抽象类来通过重写想用的方法的方式来实现。这个抽象类就是适配器。
 *好处:不需要完全实现内部的所有方法,只需要选择有需要的去使用
 *原文链接:https://blog.csdn.net/weixin_40834464/article/details/82958187
 */
public class InterfaceAdapterTest {
    public static void main(String[] args) {

        RealMethod realMethod = new RealMethod();
        realMethod.B();
        realMethod.A();
        realMethod.C();
    }
}

interface MuchMethod {
    void A();

    void B();

    void C();
}

abstract class MuchMethodAdapter implements MuchMethod {
    @Override
    public void A() {

    }

    @Override
    public void B() {

    }

    @Override
    public void C() {

    }

}

class RealMethod extends MuchMethodAdapter {
    @Override
    public void B() {
        System.out.println("RealMethod中的实现B方法");
    }
}

5.代理模式

1.静态代理
/**
 * 结构型模式: 代理模式 --- 静态代理
 * 主要的思路就是把,继承同一的接口的类A,放到继承接口的类B中调用,在调用前后可以加上新的方法
 * Java中线程的设计就使用了静态代理设计模式,其中自定义线程类实现Runable接口,
 * Thread类也实现了Runalbe接口,在创建子线程的时候,
 * 传入了自定义线程类的引用,再通过调用start()方法,调用自定义线程对象的run()方法。实现了线程的并发执行。
 */
public class StaticProxyTest {
    public static void main(String[] args) {

        SuperMan superMan = new SuperMan();
        SuperManProxy superManProxy = new SuperManProxy(superMan);
        superManProxy.show();

    }
}

interface Subject {
    void show();
}

// 实现类超人
class SuperMan implements Subject {

    @Override
    public void show() {
        System.out.println("超人去购物了");
    }
}

// 代理类
class SuperManProxy implements Subject {

    private SuperMan superMan;

    public SuperManProxy(SuperMan superMan) {
        this.superMan = superMan;
    }

    @Override
    public void show() {
        // 之前做的事情
        System.out.println("==========前面做的事情========");
        // 超人自己做的事情
        superMan.show();
        // 之后做的事情
        System.out.println("==========之后做的事情========");

    }
}
2.jdk动态代理
public class JDKProxyTest {
    public static void main(String[] args) {

        UserService userService = new UserServiceImplements();


        UserService proxyByJDK = MyProxyUtil.getProxyByJDK(userService);
        // 目标对象的方法
        userService.saveUser();
        System.out.println("====================");
        // 代理的方法
        proxyByJDK.saveUser();

    }
}

interface UserService {
    void saveUser();
}

class UserServiceImplements implements UserService {

    @Override
    public void saveUser() {
        System.out.println("调用saveUser方法");
    }
}

// 代理类 --- 进行JDK动态代理 注意Proxy.newProxyInstance()方法的参数
// 参数是:被代理的类加载器,接口,重写InvocationHandler方法

class MyProxyUtil {

    public static UserService getProxyByJDK(UserService service) {

        UserService userService = (UserService) Proxy.newProxyInstance(service.getClass().getClassLoader(),
                service.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("记录日志-开始");
                        Object obj = method.invoke(service, args);
                        System.out.println("记录日志-结束");
                        return obj;
                    }
                });
        return userService;
    }
}

6.策略模式

public class StrategyTest {
    public static void main(String[] args) {
        SalesMan a = new SalesMan("A");
        a.show();
        SalesMan b = new SalesMan("B");
        b.show();
        SalesMan c = new SalesMan("C");
        c.show();

    }
}

// 销售东西,根据季节不同使用不同的策略
abstract class SaleStrategy {

    abstract void show();
}
// 春节
class AStrategy extends SaleStrategy {

    @Override
    void show() {
        System.out.println("========春节的策略==========");
    }
}
// 中秋节
class BStrategy extends SaleStrategy {

    @Override
    void show() {
        System.out.println("==========中秋节的策略======");
    }
}

// 元旦节
class CStrategy extends SaleStrategy {

    @Override
    void show() {
        System.out.println("===========元旦节的策略========");
    }
}

// 不同销售人员使用不同的策略

class SalesMan {

    private SaleStrategy saleStrategy;

    public SalesMan(String festival) {

        switch (festival) {
            case "A":
                saleStrategy = new AStrategy();
                break;
            case "B":
                saleStrategy = new BStrategy();
                break;
            case "C":
                saleStrategy = new CStrategy();
                break;
        }
    }

    // 向客户展示商品
    public void show() {
        saleStrategy.show();
    }
}

7.模板模式

public class TestTemplateTest {
    public static void main(String[] args) {

        TemplateClass templateClass = new BaoCai();
        templateClass.pourSauce();
        templateClass = new Tomato();
        templateClass.pourSauce();

    }
}

//模板方法模式简单来说,就是定义一个公共模板,
// 比如说,我要做菜,做炒空心菜和蒜蓉两种菜,做这两种菜的步骤是不完全一样,但是重复的步骤有很多的过程
// 因此我可以定义一个炒菜模板,如下:
abstract class TemplateClass {
    // 模板方法,用来控制炒菜的流程 (炒菜的流程是一样的-复用)
    // 申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序
    final void cookProcess() {
        // 第一步:倒油 --- 一样的
        this.pourOil();
        // 第二步:热油 --- 一样的
        this.HeatOil();
        // 第三步:倒蔬菜 -- 不一样
        this.pourVegetable();
        // 第四步:倒调味料 -- 不一样
        this.pourSauce();
        // 第五步:翻炒 --- 一样的
        this.fry();
    }

    void pourOil(){
        System.out.println("========倒油=========");
    }

    void HeatOil() {
        System.out.println("==========热油===========");
    }

    abstract void pourVegetable();

    abstract void pourSauce();

    void fry() {
        System.out.println("===========翻炒==========");
    }

}

// 炒包菜
class BaoCai extends TemplateClass {

    @Override
    void pourVegetable() {
        System.out.println("==========放入包菜==========");
    }

    @Override
    void pourSauce() {

        System.out.println("========放包菜的调料=====");
    }
}

// 炒土豆
class Tomato extends TemplateClass {

    @Override
    void pourVegetable() {
        System.out.println("=========放入土豆========");
    }

    @Override
    void pourSauce() {

        System.out.println("==========放入土豆的调料=========");
    }
}

8.观察者模式

public class ObserverTest {
    public static void main(String[] args) {
        Subject subject = new Teacher();

        Observer a = new StudentA();
        Observer b = new StudentB();
        Observer c = new StudentC();

        subject.add(a);
        subject.add(b);
        subject.add(c);

        subject.notifyObserver();
        System.out.println("移除studentb之后");
        subject.delete(b);
        subject.notifyObserver();
    }
}

// 被观察者
abstract class Subject {

    protected List<Observer> lists = new ArrayList<>();

    // 添加
    public abstract void add(Observer observer);

    // 删除
    public abstract void delete(Observer observer);

    // 通知
    public abstract void notifyObserver();
}

// 具体的被观察者
class Teacher extends Subject {

    @Override
    public void add(Observer observer) {
        lists.add(observer);
    }

    @Override
    public void delete(Observer observer) {
        lists.remove(observer);
    }

    @Override
    public void notifyObserver() {
        int size = lists.size();
        for (int i = 0; i < size; i++) {
            lists.get(i).change();
        }
    }
}

// 观察者
abstract class Observer {

    public abstract void change();
}

// 学生A
class StudentA extends Observer {

    @Override
    public void change() {
        System.out.println("a变化了===");
    }
}

class StudentB extends Observer {

    @Override
    public void change() {
        System.out.println("b变化了===");
    }
}

class StudentC extends Observer {

    @Override
    public void change() {
        System.out.println("c变化了===");
    }
}

9.装饰器模式

优点:装饰类和被装饰类都互不受影响,不会改变原有逻辑,并且使用装饰器模式可以动态扩展功能

缺点:如果装饰类还是一个接口,那么就可能存在多层装饰,维护起来还是比较麻烦

与代理模式的区别:确实装饰器模式看起来跟代理模式特别的相似,但是对于代理模式来说可以作出一些操作改变原有代码,也就是说带有侵入性。而装饰器的定义是不能改变原有方法,只能对原有方法作出增强

public class DecoratorTest {
    public static void main(String[] args) {
        Animal dog = new Bird();
        dog.fly();
        System.out.println("============增强===========");
        final AnimalDecorator decorator = new BirdDecorator(dog);
        decorator.fly();
    }
}


interface Animal {
    void fly();
}

class Bird implements Animal {

    @Override
    public void fly() {
        System.out.println("dog fly");
    }
}

abstract class AnimalDecorator implements Animal {
    Animal animal;
    
    public AnimalDecorator(Animal animal) {
        this.animal = animal;
    }

    @Override
    public void fly() {
        animal.fly();
    }
}
class BirdDecorator extends AnimalDecorator {

    public BirdDecorator(Animal animal) {
        super(animal);
    }

    @Override
    public void fly() {
        super.fly();
        System.out.println("Bird增强");
    }
}

10.状态模式

当一个对象内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

你发现你的代码里面存在一个很长的if else列表,而这些分支都是因为不同状态下执行的操作不一样时考虑使用此模式

状态模式与策略模式区别

状态模式与策略模式的UML类图都是一样的,从表面上看他们非常相似。特别是将状态切换任务放在Context中做的时候就更像了,但是其背后的思想却非常不同。

  • 策略模式定义了一组可互相代替的算法,这一组算法对象完成的是同一个任务,只是使用的方式不同,例如同样是亿万富翁,马云通过卖东西实现,而王思聪通过继承实现。
  • 状态模式不同的状态完成的任务完全不一样。
public class StateTest {
    public static void main(String[] args) {

        // 默认状态
        final Context context = new Context();// 状态管理者
        context.request();

        // 接单状态
        final OrderState orderState = new OrderState();
        context.setState(orderState);
        context.request();

        // 出库状态
        final ProductOutState productOutState = new ProductOutState();
        context.setState(productOutState);
        context.request();
    }
}

class Context {

    private State state;

    public Context() {
        state = new WaitState();
    }
    public Context(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void request() {
        state.action();
    }
}

interface State {
    void action();
}

class WaitState implements State {

    @Override
    public void action() {
        System.out.println("商家等待接单中...");
    }
}

class OrderState implements State {

    @Override
    public void action() {
        System.out.println("商家已经接单,正在处理中...");
    }
}

class ProductOutState implements State {

    @Override
    public void action() {
        System.out.println("商品已经出库...");
    }
}

11.享元模式

享元模式,防止创建大量重复对象,将其缓存起来,如查询车票信息

不同的地方到不同地方的票为一个实体对象

public class FlyWeightTest {
    public static void main(String[] args) {
        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                final Ticket ticket = TicketFactory.getTicket("成都", "绵阳");
                ticket.showTicketInfo();
            }, Integer.toString(i)).start();
        }

        for (int i = 0; i < 20; i++) {
            new Thread(() -> {
                final Ticket ticket = TicketFactory.getTicket("成都", "上海");
                ticket.showTicketInfo();
            }, Integer.toString(i)).start();
        }
    }
}

// 享元模式,防止创建大量重复对象,将其缓存起来
// 车票查询信息
interface Ticket {
    void showTicketInfo();
}

// 火车票
class TrainTicket implements Ticket {

    private final String from;
    private final String to;
    private final int price;

    public TrainTicket(String from, String to) {
        this.from = from;
        this.to = to;
        this.price = new Random().nextInt(1000);
    }

    @Override
    public void showTicketInfo() {
        System.out.println("从" + this.from
                + "到" + this.to
                + "价格为" + this.price
                + ";当前线程:" + Thread.currentThread().getName()
                + ",ticket:" + this);
    }
}


class TicketFactory {

    private static final Map<String, Ticket> ticketMap = new ConcurrentHashMap<>(10);

    public synchronized static Ticket getTicket(String from, String to) {
        String key = from + "-" + to;
        if (ticketMap.containsKey(key)) {
            return ticketMap.get(key);
        }
        final TrainTicket trainTicket = new TrainTicket(from, to);
        ticketMap.put(key, trainTicket);
        return trainTicket;
    }

}

12.桥接模式

1.桥接模式(Bridge Pattern)

将抽象部分与它的实现部分分离,使它们都可以独立地变化

2.适用环境
  • 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
  • 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
  • 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用
3.问题

假如你有一个几何形状Shape类,从它能扩展出两个子类:圆形Circle和 方形Square. 你希望对这样的类层次结构进行扩展以使其包含颜色,所以你打算创建名为红色Red和蓝色Blue的形状子类. 但是,由于你已有两个子类, 所以总共需要创建四个类才能覆盖所有组合, 例如 蓝色圆形BlueCircle和 红色方形RedSquare

public class BridgePatternTest {

    public static void main(String[] args) {
        ColorApi blue = new BlueColor();
        ColorApi red = new RedColor();

        Shape circle = new Circle(blue);
        circle.draw();
        System.out.println("--------------------");
        Shape rectangle = new Rectangle(red);
        rectangle.draw();
    }
}

interface ColorApi {
    void paint();
}

class BlueColor implements ColorApi {
    @Override
    public void paint() {
        System.out.println("蓝色...");
    }
}

class RedColor implements ColorApi {
    @Override
    public void paint() {
        System.out.println("红色...");
    }
}

abstract class Shape {

    ColorApi colorApi;

    public Shape(ColorApi colorApi) {
        this.colorApi = colorApi;
    }

    public abstract void draw();
}

class Circle extends Shape {

    public Circle(ColorApi colorApi) {
        super(colorApi);
    }

    @Override
    public void draw() {
        System.out.println("我是圆形");
        super.colorApi.paint();
    }
}

class Rectangle extends Shape {

    public Rectangle(ColorApi colorApi) {
        super(colorApi);
    }

    @Override
    public void draw() {
        System.out.println("我是长方形");
        super.colorApi.paint();
    }
}

参考链接:https://blog.csdn.net/weixin_40834464/article/details/82958187

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值