观察者模式使用场景:一个对象对其他对象有影响的时候
- 汇率对出口成本或进口利率或者公司利润率影响。
- 根据上下课铃声,老师和学生进行的事件不同。
package observer;
import java.util.*;
public class BellEventTest
{
public static void main(String[] args)
{
BellEventSource bell=new BellEventSource(); //铃(事件源)
bell.addPersonListener(new TeachEventListener()); //注册监听器(老师)
bell.addPersonListener(new StuEventListener()); //注册监听器(学生)
bell.ring(true); //打上课铃声
System.out.println("------------");
bell.ring(false); //打下课铃声
}
}
//铃声事件类:用于封装事件源及一些与事件相关的参数
class RingEvent extends EventObject
{
private static final long serialVersionUID=1L;
private boolean sound; //true表示上课铃声,false表示下课铃声
public RingEvent(Object source,boolean sound)
{
super(source);
this.sound=sound;
}
public void setSound(boolean sound)
{
this.sound=sound;
}
public boolean getSound()
{
return this.sound;
}
}
//目标类:事件源,铃
class BellEventSource
{
private List<BellEventListener> listener; //监听器容器
public BellEventSource()
{
listener=new ArrayList<BellEventListener>();
}
//给事件源绑定监听器
public void addPersonListener(BellEventListener ren)
{
listener.add(ren);
}
//事件触发器:敲钟,当铃声sound的值发生变化时,触发事件。
public void ring(boolean sound)
{
String type=sound?"上课铃":"下课铃";
System.out.println(type+"响!");
RingEvent event=new RingEvent(this, sound);
notifies(event); //通知注册在该事件源上的所有监听器
}
//当事件发生时,通知绑定在该事件源上的所有监听器做出反应(调用事件处理方法)
protected void notifies(RingEvent e)
{
BellEventListener ren=null;
Iterator<BellEventListener> iterator=listener.iterator();
while(iterator.hasNext())
{
ren=iterator.next();
ren.heardBell(e);
}
}
}
//抽象观察者类:铃声事件监听器
interface BellEventListener extends EventListener
{
//事件处理方法,听到铃声
public void heardBell(RingEvent e);
}
//具体观察者类:老师事件监听器
class TeachEventListener implements BellEventListener
{
public void heardBell(RingEvent e)
{
if(e.getSound())
{
System.out.println("老师上课了...");
}
else
{
System.out.println("老师下课了...");
}
}
}
//具体观察者类:学生事件监听器
class StuEventListener implements BellEventListener
{
public void heardBell(RingEvent e)
{
if(e.getSound())
{
System.out.println("同学们,上课了...");
}
else
{
System.out.println("同学们,下课了...");
}
}
}
**观察者模式扩展,**通过 java.util.Observable 类和 java.util.Observer 接口定义了观察者模式,只要实现它们的子类就可以编写观察者模式实例。
- void addObserver(Observer o) 方法:用于将新的观察者对象添加到向量中。
- void notifyObservers(Object arg) 方法:调用向量中的所有观察者对象的 update。方法,通知它们数据发生改变。通常越晚加入向量的观察者越先得到通知。
- void setChange() 方法:用来设置一个 boolean 类型的内部标志位,注明目标对象发生了变化。当它为真时,notifyObservers() 才会通知观察者。
- Observer 接口是抽象观察者,它监视目标对象的变化,当目标对象发生变化时,观察者得到通知,并调用 void update(Observable o,Object arg) 方法,进行相应的工作。
package observer;
import java.util.Observer;
import java.util.Observable;
public class CrudeOilFutures
{
public static void main(String[] args)
{
OilFutures oil=new OilFutures();
Observer bull=new Bull(); //多方
Observer bear=new Bear(); //空方
oil.addObserver(bull);
oil.addObserver(bear);
oil.setPrice(10);
oil.setPrice(-8);
}
}
//具体目标类:原油期货
class OilFutures extends Observable
{
private float price;
public float getPrice()
{
return this.price;
}
public void setPrice(float price)
{
super.setChanged() ; //设置内部标志位,注明数据发生变化
super.notifyObservers(price); //通知观察者价格改变了
this.price=price ;
}
}
//具体观察者类:多方
class Bull implements Observer
{
public void update(Observable o,Object arg)
{
Float price=((Float)arg).floatValue();
if(price>0)
{
System.out.println("油价上涨"+price+"元,多方高兴了!");
}
else
{
System.out.println("油价下跌"+(-price)+"元,多方伤心了!");
}
}
}
//具体观察者类:空方
class Bear implements Observer
{
public void update(Observable o,Object arg)
{
Float price=((Float)arg).floatValue();
if(price>0)
{
System.out.println("油价上涨"+price+"元,空方伤心了!");
}
else
{
System.out.println("油价下跌"+(-price)+"元,空方高兴了!");
}
}
}
油价上涨10.0元,空方伤心了!
油价上涨10.0元,多方高兴了!
油价下跌8.0元,空方高兴了!
油价下跌8.0元,多方伤心了!
代理模式
- 真实主题与代理主题一一对应,增加真实主题也要增加代理。
- 设计代理以前真实主题必须事先存在,不太灵活。采用动态代理模式可以解决以上问题,如 SpringAOP,其结构图如图 4 所示。
单例模式应用:
- 用懒汉式单例模式模拟产生美国当今总统对象。分析:在每一届任期内,美国的总统只有一人,所以本实例适合用单例模式实现,图 2 所示是用懒汉式单例实现的结构图。
- 在应用场景中,某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号等。
- 当对象需要被共享的场合。由于单例模式只允许创建一个对象,共享该对象可以节省内存,并加快对象访问速度。如 Web 中的配置对象、数据库的连接池等。
- 当某类需要频繁实例化,而创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等。
public class SingletonLazy
{
public static void main(String[] args)
{
President zt1=President.getInstance();
zt1.getName(); //输出总统的名字
President zt2=President.getInstance();
zt2.getName(); //输出总统的名字
if(zt1==zt2)
{
System.out.println("他们是同一人!");
}
else
{
System.out.println("他们不是同一人!");
}
}
}
class President
{
private static volatile President instance=null; //保证instance在所有线程中同步
//private避免类在外部被实例化
private President()
{
System.out.println("产生一个总统!");
}
public static synchronized President getInstance()
{
//在getInstance方法上加同步
if(instance==null)
{
instance=new President();
}
else
{
System.out.println("已经有一个总统,不能产生新总统!");
}
return instance;
}
public void getName()
{
System.out.println("我是美国总统:特朗普。");
}
}
抽象工厂模式:
应用实例:
农场中除了像畜牧场一样可以养动物,还可以培养植物,如养马、养牛、种菜、种水果等,所以本实例比前面介绍的畜牧场类复杂,必须用抽象工厂模式来实现。
package AbstractFactory;
import java.awt.*;
import javax.swing.*;
public class FarmTest
{
public static void main(String[] args)
{
try
{
Farm f;
Animal a;
Plant p;
f=(Farm) ReadXML.getObject();
a=f.newAnimal();
p=f.newPlant();
a.show();
p.show();
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
//抽象产品:动物类
interface Animal
{
public void show();
}
//具体产品:马类
class Horse implements Animal
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工厂模式测试");
public Horse()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("动物:马"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/A_Horse.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
}
public void show()
{
jf.setVisible(true);
}
}
//具体产品:牛类
class Cattle implements Animal
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工厂模式测试");
public Cattle() {
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("动物:牛"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/A_Cattle.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
}
public void show()
{
jf.setVisible(true);
}
}
//抽象产品:植物类
interface Plant
{
public void show();
}
//具体产品:水果类
class Fruitage implements Plant
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工厂模式测试");
public Fruitage()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("植物:水果"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/P_Fruitage.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
}
public void show()
{
jf.setVisible(true);
}
}
//具体产品:蔬菜类
class Vegetables implements Plant
{
JScrollPane sp;
JFrame jf=new JFrame("抽象工厂模式测试");
public Vegetables()
{
Container contentPane=jf.getContentPane();
JPanel p1=new JPanel();
p1.setLayout(new GridLayout(1,1));
p1.setBorder(BorderFactory.createTitledBorder("植物:蔬菜"));
sp=new JScrollPane(p1);
contentPane.add(sp, BorderLayout.CENTER);
JLabel l1=new JLabel(new ImageIcon("src/P_Vegetables.jpg"));
p1.add(l1);
jf.pack();
jf.setVisible(false);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//用户点击窗口关闭
}
public void show()
{
jf.setVisible(true);
}
}
//抽象工厂:农场类
interface Farm
{
public Animal newAnimal();
public Plant newPlant();
}
//具体工厂:韶关农场类
class SGfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新牛出生!");
return new Cattle();
}
public Plant newPlant()
{
System.out.println("蔬菜长成!");
return new Vegetables();
}
}
//具体工厂:上饶农场类
class SRfarm implements Farm
{
public Animal newAnimal()
{
System.out.println("新马出生!");
return new Horse();
}
public Plant newPlant()
{
System.out.println("水果长成!");
return new Fruitage();
}
}
适配器模式应用场景:
- 以前开发的系统存在满足新系统功能需求的类,但其接口同新系统的接口不一致。
- 使用第三方提供的组件,但组件接口定义和自己要求的接口定义不同。
package adapter;
//目标接口
interface TwoWayTarget
{
public void request();
}
//适配者接口
interface TwoWayAdaptee
{
public void specificRequest();
}
//目标实现
class TargetRealize implements TwoWayTarget
{
public void request()
{
System.out.println("目标代码被调用!");
}
}
//适配者实现
class AdapteeRealize implements TwoWayAdaptee
{
public void specificRequest()
{
System.out.println("适配者代码被调用!");
}
}
//双向适配器
class TwoWayAdapter implements TwoWayTarget,TwoWayAdaptee
{
private TwoWayTarget target;
private TwoWayAdaptee adaptee;
public TwoWayAdapter(TwoWayTarget target)
{
this.target=target;
}
public TwoWayAdapter(TwoWayAdaptee adaptee)
{
this.adaptee=adaptee;
}
public void request()
{
adaptee.specificRequest();
}
public void specificRequest()
{
target.request();
}
}
//客户端代码
public class TwoWayAdapterTest
{
public static void main(String[] args)
{
System.out.println("目标通过双向适配器访问适配者:");
TwoWayAdaptee adaptee=new AdapteeRealize();
TwoWayTarget target=new TwoWayAdapter(adaptee);
target.request();
System.out.println("-------------------");
System.out.println("适配者通过双向适配器访问目标:");
target=new TargetRealize();
adaptee=new TwoWayAdapter(target);
adaptee.specificRequest();
}
}