Subject
被观察的目标Observer
观察者
当Subject
(Subject的子类)对象的发生改变的时候,通知所有的观察者,观察者做出响应。
代码(此处使用JAVA提供的Observable
类/Observer
接口):
public class Account extends Observable {
private float mMoney = 0.0f;
public void add(float money ){
mMoney += money;
this.setChanged();
this.notifyObservers(mMoney);
}
}
public class User implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("存款变了,通知User,存款为"+arg);
}
}
public class Main {
public static void main(String[] args) {
Observer user = new User();
Observer user2 = new User2();
Account account = new Account();
account.addObserver(user);
account.addObserver(user2);
account.add(99.f);
}
}
在此处贴上Observable
的setChanged()
和notifyObservers()
方法
protected synchronized void setChanged() {
changed = true;
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
代码很清晰了,在notifyObservers()
方法中,对所有注册的观察者进行通知更新。
Subject
共用接口,其中为被代理的方法。RealSubject
被代理对象Proxy
代理对象
代理即通过另一个类完成一个类改完成的方法,并在其基础上可以对其作出改变。在上图中,是通过聚合的方式。通过聚合或继承的方法实现代理,有兴趣可以看看java的代理实现,主要有两个类,Proxy
、InvocationHandler
。
代码(此处采用的实现方式是JDK代理)
public interface Movable {
void move();
}
public class Car implements Movable {
@Override
public void move() {
System.out.println("汽车运行中");
}
}
public class TimeProxy implements InvocationHandler {
private Movable movable;
public TimeProxy(Movable mov){
movable = mov;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("汽车开始运行");
long start = System.currentTimeMillis();
Object obj = method.invoke(movable, args);
long end = System.currentTimeMillis();
System.out.println("骑车结束运行,运行时间为:"+(end-start)+"毫秒");
return obj;
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car();
TimeProxy timeProxy = new TimeProxy(car);
Movable movable = (Movable) Proxy.newProxyInstance(Car.class.getClassLoader(), Car.class.getInterfaces(), timeProxy);
movable.move();
}
}
单例模式,即在程序运行期间,单例类最多只可以有一个实例存在。单例模式的实现方法很多,各有优缺点,在此采用枚举实现单例(Effective Java Edition 2 第二章/第三条)。
public enum BoyFriend {
INSTANCE;
public void whatsName() {
System.out.println("code:" + this.hashCode());
}
}
public class Main {
public static void main(String[] args) {
BoyFriend boyFriend = BoyFriend.INSTANCE;
boyFriend.whatsName();
boyFriend.whatsName();
}
}
实现非常简单,但是优点众多:线程安全、无法反射攻击、自动提供序列化支持等。。
Handler
接口,规定传递请求的方法。ConcreteHandleA
实现类,请求的具体执行者。Client
客户端,发出请求
责任链模式,即通过一个链式的结构去处理请求,在每个节点,可以选择是通过还不是通过,通过即前往下一个节点,不通过,即退出责任链。
下面模拟一个场景,女孩发出约会,看男孩有没有钱、房、车,有的话,继续看,没有就byebye,看代码。
public class Boy {
private boolean hasMoney;
private boolean hasCar;
private boolean hasHouse;
private Boy(){}
public Boy(boolean hasMoney, boolean hasCar, boolean hasHouse) {
this.hasMoney = hasMoney;
this.hasCar = hasCar;
this.hasHouse = hasHouse;
}
public boolean isHasMoney() {
return hasMoney;
}
public void setHasMoney(boolean hasMoney) {
this.hasMoney = hasMoney;
}
public boolean isHasCar() {
return hasCar;
}
public void setHasCar(boolean hasCar) {
this.hasCar = hasCar;
}
public boolean isHasHouse() {
return hasHouse;
}
public void setHasHouse(boolean hasHouse) {
this.hasHouse = hasHouse;
}
}
public interface Response {
void deliverResponse(Boy boy);
}
public class CarResponse implements Response{
private Response next;
public CarResponse(Response res){
next = res;
}
@Override
public void deliverResponse(Boy boy) {
if(boy.isHasCar()){
System.out.println("有车呀,么么哒");
if(next != null){
next.deliverResponse(boy);
}
}else{
System.out.println("没车你说个jb");
}
}
}
public class HouseResponse implements Response{
private Response next;
public HouseResponse(Response res){
next = res;
}
@Override
public void deliverResponse(Boy boy) {
if(boy`这里写代码片`.isHasHouse()){
System.out.println("有房呀,么么哒");
if(next != null){
next.deliverResponse(boy);
}
}else{
System.out.println("没房你说个jb.");
}
}
}
public class MoneyResponse implements Response{
private Response next;
public MoneyResponse(Response res){
next = res;
}
@Override
public void deliverResponse(Boy boy) {
if(boy.isHasMoney()){
System.out.println("有钱呀,么么哒");
if(next != null){
next.deliverResponse(boy);
}
}else{
System.out.println("没钱你说个jb");
}
}
}
public class Gril {
public void date(Boy boy){
Response r = new CarResponse(new HouseResponse(new MoneyResponse(null)));
r.deliverResponse(boy);
}
}
public class Main {
public static void main(String[] args) {
Gril gril = new Gril();
Boy boy = new Boy(false,true,false);
gril.date(boy);
}
}
很清晰了,date()
方法相当于发出一个请求,在各个Response
中进行传递。
享元模式,即通过建立一个缓存机制,将对象进行重用,而不需要每次调用进行重新创建,在本例中,使用HashTable
实现对象缓存。
本例中,创建了两个实现Util
接口的实现类,通过单例的UtilBox
工厂获取Util
的实现类,并在其中实现享元。
public interface Util {
void use();
void putoff();
}
public class Forceps implements Util {
public Forceps(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void use() {
System.out.println("用了个钳子");
}
@Override
public void putoff() {
System.out.println("放下了钳子");
}
}
public class Wrench implements Util {
public Wrench(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void use() {
System.out.println("用了个扳手");
}
@Override
public void putoff() {
System.out.println("放下了扳手");
}
}
public enum UtilBox {
INSTANCE;
UtilBox() {
utilBoxTable = new Hashtable<>();
}
private Hashtable utilBoxTable;
public Util getUtil(String utilName){
Util util = utilBoxTable.get(utilName);
if(util != null){
return util;
}
if("wrench".equals(utilName)){
util = new Wrench();
utilBoxTable.put("wrench",util);
}else if("forceps".equals(utilName)){
util = new Forceps();
utilBoxTable.put("forceps",util);
}else{
throw new IllegalArgumentException("utilName is not exists");
}
return util;
}
}
public class Main {
public static void main(String[] args) {
//通过观察,发现加载时间明显改变了
UtilBox.INSTANCE.getUtil("wrench").use();
UtilBox.INSTANCE.getUtil("wrench").use();
UtilBox.INSTANCE.getUtil("forceps").use();
UtilBox.INSTANCE.getUtil("forceps").use();
}
}
代码没有什么难度,明白其中的意思即可。
Caretaker 记录状态的容器
备忘录模式,即在不破坏原类封装的条件下,加入存储类和操作类记录原有类的状态变化。
public class Account {
private float money;
public float getMoney() {
return money;
}
public void setMoney(float money) {
this.money = money;
}
public Record save(){
return new Record(money);
}
public void restore(Record record){
money = record.money;
}
@Override
public String toString() {
return "账户余额为:"+money;
}
}
public class Record {
float money;
public Record(float money) {
this.money = money;
}
}
public class Memory {
private Stack memo;
public Memory(){
memo = new Stack<>();
}
public Record get(){
return memo.pop();
}
public void push(Record r){
memo.push(r);
}
}
public class Main {
public static void main(String[] args) {
Memory memory = new Memory();
Account a = new Account();
a.setMoney(12.0f);
memory.push(a.save());
System.out.println(a.toString());
a.setMoney(25.0f);
memory.push(a.save());
System.out.println(a.toString());
memory.get();
a.restore(memory.get());
System.out.println(a.toString());
}
}
代码依然没难度,看明白就好。
图片有点看不清楚,意思就是,通过聚合的方式,向原有类中添加功能。
public abstract class Duck {
public void swim(){
System.out.println(this.getClass().getSimpleName()+"游啊游");
}
public abstract void display();
}
public interface FlyStratagy {
void fly();
}
public interface FlyStratagy {
void fly();
}
public class WildDuck extends Duck {
private FlyStratagy fly;
public WildDuck(){
fly = new FlyWithWin();
}
@Override
public void display() {
System.out.println("灰色的鸭子");
}
public void fly(){
fly.fly();
}
}
public class Main {
public static void main(String[] args) {
WildDuck duck = new WildDuck();
duck.fly();
duck.swim();
duck.display();
}
}
策略模式的好处就是,将功能的添加采用聚合的模式,那么不会像接口那样,需要强制性的实现,并且策略可复用,在其他需要这个策略的地方,直接引入即可。
策略模式的详细说明可以参考《Effective Java edition 2》第四章第十八条:接口优于抽象类。
状态模式,即通过状态,决定当前的行为,在发生了一定行为之后,进入下一个状态。
public class Light {
private LightState lightState;
public Light(){
lightState = new OffState();
}
public void setLightState(LightState ls){
lightState = ls;
}
public void switcher(){
lightState.handleState(this);
}
}
public interface LightState {
void handleState(Light light);
}
public class OnState implements LightState {
@Override
public void handleState(Light light) {
System.out.println("灯开着了");
light.setLightState(new OffState());
}
}
public class OffState implements LightState {
@Override
public void handleState(Light light) {
System.out.println("灯关了");
light.setLightState(new OnState());
}
}
public class Main {
public static void main(String[] args) {
Light light = new Light();
light.switcher();
light.switcher();
light.switcher();
light.switcher();
}
}
通过light
的switcher()
方法,改变了状态,触发状态改变,改变了light
的行为,一直循环。
2015年6月16日 更新至此.
ps:以上图片均来自百度,侵删。
ps2:水平有限,如有不足,请指出。
ps3:代码可以在:简单设计模式Java实现 - github找到