简单介绍一些设计模式

1.最常用的工厂模式

package cn.cnm.springboot.util;

public class GCMS {
    public static void main(String[] args){
        Factory f=new Factory();
        GCFood g=f.getFood("dog");
        g.show();
    }
}
interface GCFood{
    public abstract void show();
}
class Dog implements GCFood{

    @Override
    public void show() {
        System.out.println("狗肉");
    }
}
class Tiger implements GCFood{

    @Override
    public void show() {
        System.out.println("老虎肉");
    }
}
class Factory{
    public GCFood getFood(String f){
        if(f=="" || f==null)
            return null;
        if(f.equals("dog")){
            return new Dog();
        }else if(f.equals("tiger")){
            return new Tiger();
        }
        return null;
    }
}

这个模式用在局部变量上面比较好。当有很多具体子类时,不用工厂模式的话,当换了一个实现类,类名改了,原来是牛肉现在换成狗肉,就需要在用到的地方改类名。用了工厂模式,那就只需要改工厂类逻辑。

为什么用在局部变量?因为成员变量其实是不需要用工厂模式的。用接口就行了,类里面用到成员变量的地方全都用接口,在构造器进行接口的初始化,这样换了一个实现类,就只改一下初始化这个类的地方就行了,这里初始化这个类一定是其他的类。

Xxx(Food f){

this.f=f;

}

上面就是简单的初始化了。

2.装饰者模式

package cn.cnm.springboot.util;

public class ZSZ {
    public static void main(String[] args){
        Food f1=new Chicken();
        FoodDec fd=new FoodDec(f1);
        FoodDec_ fd_=new FoodDec_(fd);
        fd.getName();
        fd_.getName();
    }
}
abstract class Food{
    public String name;
    public abstract void getName();
}
class Chicken extends Food{
    Chicken(){
        name="红烧鸡";
    }
    @Override
    public void getName() {
        System.out.println(name);
    }
}
class Fish extends Food{
    Fish(){
        name="清蒸鱼";
    }
    @Override
    public void getName() {
        System.out.println(name);
    }
}

abstract class _Food extends Food{
    protected Food f;
    public _Food(Food f){
        this.f=f;
    }
}

class FoodDec extends _Food{
    FoodDec(Food f){
        super(f);
    }
    @Override
    public void getName() {
        System.out.print("eat ");
        f.getName();
    }
}
class FoodDec_ extends _Food{

    public FoodDec_(Food f) {
        super(f);
    }

    @Override
    public void getName() {
        System.out.print("make ");
        f.getName();
    }
}

这个模式有下面几个作用:

1)避免子类爆炸,如同样是食物,有肉还有蔬菜,同样是肉有鸡鸭鱼鹅肉,同样是鸡肉有红烧清蒸等,这样组合就有很多种,最底层的子类就太多了,有红烧鸡肉还有红烧鸭肉还有红烧鱼肉,用了装饰者模式,我们只需要把肉,鸡鸭鱼鹅,红烧清蒸分别弄个装饰器,最后红烧鸡肉就是 new 食物(new 肉(new 鸡肉(红烧))),对比一下用的类就少很多。

2)加强功能,同样的奶茶,有绿奶茶,有白奶茶,有黑奶茶,不同奶茶价格不一样,我们可以在奶茶抽象类定义一个价格方法,具体的珍珠奶茶继承一下奶茶,把价格方法实现了,给个具体的基础价格3块,绿白黑作为装饰器继承_奶茶(这个_奶茶就像上面代码中的抽象类_food一样,继承food把food的抽象方法带过来,构造器继承他就有了food的抽象方法实现。然后在里面定义一个food成员变量,并在构造器初始化,作用是防止代码冗余,因为构造器需要写这些东西,同时也解耦合,因为构造器不需要写这些就没有food的成员变量了),这样所有的构造器都有了价格这个方法,可以在这个方法对珍珠奶茶的具体价格进行加强,如

int 价格(){

return 珍珠奶茶.价格()+5;

}

这个等于间接的实现了代理的功能。

3.发布订阅模式

package cn.cnm.springboot.util;

public class fd {
    public static void main(String[] args){
    Fbz f=new Fbz();
    Zx z=new Zx();
    Dyz d1=new Dyz();
    Dyz d2=new Dyz();
    Dyz d3=new Dyz();
    f.zx=z;
    z.ds[0]=d1;
    z.ds[1]=d2;
    z.ds[2]=d3;
    f.update("closer");
    }

}
class Fbz{
    Zx zx;
    void update(String msg){
        zx.update(msg);
    }
}
class Zx{
    Dyz[] ds=new Dyz[3];
    void update(String msg){
        for(int i=0;i<ds.length;i++){
            ds[i].update(msg);
        }
    }
}
class Dyz{
    void update(String msg){
        System.out.println("update msg "+msg);
    }
}

这个模式跟观察者模式不一样,观察者模式是下面这个样子:

package cn.cnm.springboot.util;

public class Gcz {
    public static void main(String[] args){
    Gczz g=new Gczz();
    Bgcz b=new Bgcz(g);
    b.update("huirenbujuan");
    }
}
class Bgcz{
    Gczz g;
    Bgcz(Gczz g){
        this.g=g;
    }
    void update(String msg){
        g.update(msg);
    }
}
class Gczz{
    void update(String msg){
        System.out.println(msg);
    }
}

可以看见是发布者发布了消息,在发布消息的方法里马上调用订阅者(成员变量)更新消息,而发布订阅模式则在中间加了一个中间件,发布者更新了消息,就马上通知中间件更新消息,中间件更新消息的方法内调用订阅者(订阅者是存放在一个数组或集合里)让他们更新消息。上面的代码并不齐全,应该还有订阅者订阅退订以及中间件存储发布者更新的消息。

两者就是一个中间件的差别,但这个中间价可以做很多事。下面是区别:

发布订阅模式是单向异步的,观察者模式是同步的,发布者更新消息了,就可以继续执行其他代码,不需要等待订阅者更新消息的带啊执行,这些全都交给中间件

发布订阅模式的消息可以用队列存储,降低发布者崩溃的可能型

同时两者也解耦合,订阅者并不是一成不变的可能会增加也会退订,降低运维难度,因为很多时候订阅者有很多,而且更新的操作可能也有很多。另外由于数据存储在中间件里,所以可以设置消息的处理顺序

数据存放在中间件内,所以发生意外也能在处理数据失败后恢复数据

4.生产消费者模式

 package com.sequ.test;

import java.util.LinkedList;
import java.util.Queue;

public class AnotherTest {

    public static void main(String[] args){
        Queue q=new LinkedList();
        System.out.println("start");
        Thread t1=new Producer(q);
        Thread t2=new Customer(q);
        t1.start();
        t2.start();
        System.out.println("game over");
    }
    
}
class Producer extends Thread{
    private Queue shareQ;
    public Producer(Queue q){
        this.shareQ=q;
    }
    @Override
    public void run() {
        for(int i=0;i<100;i++){
        synchronized (shareQ) {
            while(shareQ.size()>=1){
                
                try {
                    System.out.println("生产者在等。。。");
                    shareQ.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
                 shareQ.offer("一件产品");
                 System.out.println("生产了"+i+"件产品");
                 shareQ.notify();//激活一个线程,但能不能激活成功不一定,因为需要再判断是否满足激活条件,也就是wait的条件,满足wait的条件则继续等待
        }
    }
    }
    
}
class Customer extends Thread{
    private Queue shareQ;
    public Customer(Queue q){
        this.shareQ=q;
    }
    @Override
    public void run(){
        for(int i=0;i<100;i++){
        synchronized (shareQ) {
            while(shareQ.size()<1){
                try {
                    System.out.println("消费者在等。。。");
                    shareQ.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            shareQ.poll();
            System.out.println("消费了"+i+"件产品");
            shareQ.notify();
        }
    }
    }
}

这个模式用到了多线程的知识,也可以用其他的方法如blockingqueue等来实现拥塞控制,作用自然是原来一个线程干的事交给两个线程,提高速度。

java还有很多设计模式,不了解就不写了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值