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还有很多设计模式,不了解就不写了