目录:
1、观察者模式(Observer)
2、单例模式(Singleton)
3、策略模式(Strategy)
4、工厂方法(Factory Method)
5、抽象工厂(Abstract factory)
6、责任链(Chain of Responsibility)
7、桥接模式(Bridge)
8、命令模式(Command)
9、状态模式(State)
10、模板方法(Template Method)
11、备忘录模式(Memento)
12、门面模式(Fasade)
13、建造模式(Builder)
14、原型模式(ProtoType)
15、适配器模式(Adapter)
16、组合模式(Composite)
17、装饰模式(Decorator)
18、代理模式(Proxy)
19、享元模式(Flyweight
20、解释器模式(Interpreter)
21、迭代器模式(Iterator)
22、调停者模式(Mediator)
23、访问者模式(Visitor)
设计模式的分类:
创建型模式
1.抽象工厂模式 AbstractFactory
2.建造者模式 Builder
3.工厂方法模式 Factory Method
4.原型模式 Prototype
5.单例模式 Singleton
结构型模式
1.适配器模式 Adapter
2.桥接模式 Bridge
3.组合模式 Composite
4.装饰模式 Decorator
5.外观模式 Facade
6.享元模式 Flyweight
7.代理模式 Proxy
行为模式
1.职责链模式 Chain of Responsibility
2.命令模式 Command
3.解释器模式 Interpreter
4.迭代器模式 Iterator
5.中介者模式 Mediator
6.备忘录模式 Memento
7.观察者模式 Observer
8.状态模式 State
9.策略模式 Strategy
10.模板方法模式 Template Method
11.访问者模式 Visitor
1、观察者模式(Observer)
简单地说,观察者模式定义了一个一对多的依赖关系,让一个或多个观察者对象监察一个被观察者对象。这样一个被观察者对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动行为。
package designModels;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class TestObserver {
public static void main(String args[]) {
Observerable observedClass = new ObservedClass();
observedClass.addObserver(new RealObserver1());
observedClass.addObserver(new RealObserver2());
observedClass.addObserver(new RealObserver1());
observedClass.notifyObservers();
observedClass.setChanged(true);
observedClass.notifyObservers();
}
}
/**
* 抽象的Observer,实际Observer继承自这个接口
* @author Administrator
*/
interface Observer {
public void act(Date date, String reason, Object source);
}
/**
* 实际的Observer类,实现接口中的方法
* @author Administrator
*
*/
class RealObserver1 implements Observer {
@Override
public void act(Date date, String reason, Object source) {
System.out.println("O1 Time: " + date);
System.out.println("O1 Reason: " + reason);
System.out.println("O1 Source: " + source.getClass().getName());
}
}
class RealObserver2 implements Observer {
@Override
public void act(Date date, String reason, Object source) {
System.out.println("O2 Time: " + date);
System.out.println("O2 Reason: " + reason);
System.out.println("O2 Source: " + source.getClass().getName());
}
}
/**
* 抽象的被观察者,实际的被观察者继承自这个类
* @author Administrator
*/
interface Observerable{
public void addObserver(Observer ob);
public void delObserver(Observer ob);
public void notifyObservers();
public void setChanged(boolean isChanged);
}
/**
* 被观察者,这个类中保存着一个观察者的List,
* 有添加(删除)观察者的方法,通知观察者的方法。
* @author Administrator
*/
class ObservedClass implements Observerable{
// 保存着所有观察者的List
private List<Observer> observers = new ArrayList<Observer>();
private boolean isChanged = false;
public void setChanged(boolean isChanged) {
this.isChanged = isChanged;
}
/**
* 添加观察者的方法
* @param ob
*/
public void addObserver(Observer ob) {
if (!observers.contains(ob)) {
observers.add(ob);
}
}
/**
* 删除观察者的方法
* @param ob
*/
public void delObserver(Observer ob) {
if (observers.contains(ob)) {
observers.remove(ob);
}
}
/**
* 使所有观察者做出行为的方法
*/
public void notifyObservers() {
if(isChanged){
for (Observer ob : observers) {
ob.act(new Date(), "reason is MYY", this);
}
isChanged = false;
}
}
}
非常简略的一个版本.
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestSimpleObserver {
public static void main(String args[]) {
ObservedClass2 observedClass = new ObservedClass2();
observedClass.addObserver(new Observer2());
observedClass.addObserver(new Observer2());
observedClass.addObserver(new Observer2());
observedClass.notifyObserver();
}
}
class ObservedClass2 {
private List<Observer2> observers = new ArrayList<Observer2>();
private static int i = 0;
public void addObserver(Observer2 o) {
if (!observers.contains(o)) {
observers.add(o);
}
}
public void notifyObserver() {
for (Observer2 o : observers) {
o.act(this, i++);
}
}
}
class Observer2 {
public void act(Object source, int arg) {
System.out.println("source : " + source.getClass().getName() + " arg: "
+ arg);
}
}
2、单例模式(Singleton)
一个类只有一个实例,因此构造方法应该为私有
懒汉式:第一次需要时才创建一个实例,那么newInstance方法要加同步
饿汉式:类加载时直接创建静态实例
package designModels;
public class TestSingleton {
public static void main(String args[]) {
SingletonLazy s1 = SingletonLazy.getSingletonLazy();
SingletonLazy s2 = SingletonLazy.getSingletonLazy();
System.out.println(s1 == s2);
SingletonEager s3 = SingletonEager.getSingletonEager();
SingletonEager s4 = SingletonEager.getSingletonEager();
System.out.println(s3 == s4);
}
}
/**
* 懒汉式单例模式
* @author Administrator
*
*/
class SingletonLazy {
private static SingletonLazy s = null;
private SingletonLazy() {
}
synchronized public static SingletonLazy getSingletonLazy() {
if (s == null)
s = new SingletonLazy();
return s;
}
}
/**
* 恶汉式单例模式
* @author Administrator
*
*/
class SingletonEager {
private static SingletonEager s = new SingletonEager();
private SingletonEager() {
}
public static SingletonEager getSingletonEager() {
return s;
}
}
3、策略模式(Strategy)
策略模式实是一种“面向接口”的编程方法,根据不同的策略选择不同的实现类。
package designModels;
public class TestStrategy {
public static void main(String args[]) {
Food food = new Food(100);
Strategy s1 = new Strategy1();
Strategy s2 = new Strategy2();
food.setStrategy(s1);
System.out.println(food.getFinalPrice());
food.setStrategy(s2);
System.out.println(food.getFinalPrice());
}
}
class Food {
private double price = 0.0;
private Strategy strategy;
public Food(double price) {
this.price = price;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public double getFinalPrice() {
return strategy.getNowPrice(price);
}
}
interface Strategy {
public double getNowPrice(double price);
}
class Strategy1 implements Strategy {
public double getNowPrice(double price) {
return 0.8 * price;
}
}
class Strategy2 implements Strategy {
public double getNowPrice(double price) {
return 0.7 * price;
}
}
4、工厂方法(Factory Method)
工厂模式 :用来生产同一等级结构中的固定产品。(支持增加任意产品)
这里借用一下别人的图
package designModels;
public class TestFactory {
public static void main(String args[]){
VehicleFactory vf = new CarFactory();
Vehicle car = vf.getVehicle();
car.run();
vf = new BusFactory();
Vehicle bus = vf.getVehicle();
bus.run();
}
}
abstract class VehicleFactory {
public abstract Vehicle getVehicle();
}
class CarFactory extends VehicleFactory {
@Override
public Vehicle getVehicle() {
return new Car();
}
}
class BusFactory extends VehicleFactory {
@Override
public Vehicle getVehicle() {
return new Bus();
}
}
abstract class Vehicle {
public abstract void run();
}
class Car extends Vehicle {
@Override
public void run() {
System.out.println("Car is running");
}
}
class Bus extends Vehicle {
@Override
public void run() {
System.out.println("Bus is running");
}
}
5、抽象工厂(Abstract factory)
抽象工厂 :用来生产不同产品族的全部产品。(对于增加新的产品,无能为力;支持增加产品族)
再次借用一下别人的图
package designModels;
public class TestAbstractFactory {
public static void main(String args[]){
AbstractFactory f1 = new CarAndAppleFactory();
//f1 = new BusAndMushroomFactory(); 只用一句即可改变整个产品族
f1.getFood().show();
f1.getVehicle().run();
}
}
abstract class AbstractFactory {
public abstract Vehicle getVehicle();
public abstract Food getFood();
}
class CarAndAppleFactory extends AbstractFactory{
@Override
public Food getFood() {
return new Apple();
}
@Override
public Vehicle getVehicle() {
return new Car();
}
}
class BusAndMushroomFactory extends AbstractFactory{
@Override
public Food getFood() {
return new Mushroom();
}
@Override
public Vehicle getVehicle() {
return new Bus();
}
}
abstract class Food{
public abstract void show();
}
class Apple extends Food{
@Override
public void show() {
System.out.println("an apple!");
}
}
class Mushroom extends Food{
@Override
public void show() {
System.out.println("a mushroom!");
}
}
abstract class Vehicle{
public abstract void run();
}
class Car extends Vehicle{
@Override
public void run() {
System.out.println("Car is running");
}
}
class Bus extends Vehicle{
@Override
public void run() {
System.out.println("Bus is running");
}
}
6、责任链(Chain of Responsibility)
多个处理器对象连成一串,请求在这条链上传递
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestFilterChain {
public static void main(String args[]) {
String s = "<string> i . abc , d";
StringProcessor sp = new StringProcessor();
s = sp.process(s);
System.out.println(s);
}
}
class StringProcessor {
public String process(String s) {
FilterChain f = new FilterChain();
f.addFilter(new Filter1()).addFilter(new Filter2()).addFilter(new Filter3());
s = f.doFilter(s);
return s;
}
}
interface Filter {
String doFilter(String s);
}
class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<Filter>();
public FilterChain addFilter(Filter f) {
filters.add(f);
return this;
}
public String doFilter(String s) {
for (Filter f : filters)
s = f.doFilter(s);
return s;
}
}
class Filter1 implements Filter {
public String doFilter(String s) {
return s.replace("<", "[").replace(">", "]");
}
}
class Filter2 implements Filter {
public String doFilter(String s) {
return s.replace(",", "!").replace(".", "?");
}
}
class Filter3 implements Filter {
public String doFilter(String s) {
return s.replace("a", "A").replace("b", "B");
}
}
7、桥接模式(Bridge)
桥接模式用在两个维度上的排列组合,解耦合的时候。
桥接模式将继承关系转换为组合关系,从而降低了系统间的耦合。
例如蜡笔,3种大小,12种颜色,则需要3X12=36
而毛笔,3种大小,12种颜色,只需要3+12=15
package designModels;
public class TestBridge {
public static void main(String args[]) {
Size s = new Big();
s.setColor(new Blue());//此处是关键
s.getSize();
s.getColor().draw();
}
}
class Size {
Color color;
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public void getSize() {
}
}
class Big extends Size {
public void getSize() {
System.out.println("Big one");
}
}
class Small extends Size {
public void getSize() {
System.out.println("Small one");
}
}
class Color {
public void draw() {
}
}
class Red extends Color {
public void draw() {
System.out.println("Red one");
}
}
class Blue extends Color {
public void draw() {
System.out.println("Blue one");
}
}
class Green extends Color {
public void draw() {
System.out.println("Green one");
}
}
8、命令模式(Command)
将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式.
命令模式解耦了发送者和接受者之间联系。 发送者调用一个操作,接受者接受请求执行相应的动作,因为使用Command模式解耦,发送者无需知道接受者任何接口。
换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了.
显然这样做的好处是符合封装的特性,降低耦合度,Command是将对行为进行封装的典型模式,Factory是将创建进行封装的模式,
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestCommand {
public static void main(String args[]){
Girl girl = new Girl();
girl.ReleaseCommand();
}
}
/**
* 以一个Girl对她的Boy下一系列COMMAND为例
* Girl为命令发出者,Boy为命令执行者
* @author Administrator
*
*/
class Girl{
Boy boy = new Boy();
/**
* 命令发出者发出一系列命令
*/
public void ReleaseCommand(){
boy.addCommand(new ShoppingCommand());
boy.addCommand(new SleepCommand());
boy.executeCommands();
}
}
class Boy{
private List<Command> commands = new ArrayList<Command>();
public void addCommand(Command c){
commands.add(c);
}
public void executeCommands(){
for(Command c: commands){
c.execute();
}
}
}
/**
* Command接口,具体的Command实现此接口
* @author Administrator
*
*/
interface Command{
void execute();
}
class ShoppingCommand implements Command{
public void execute() {
System.out.println("Go shopping!");
}
}
class SleepCommand implements Command{
public void execute() {
System.out.println("Go to sleep!");
}
}
9、状态模式(State)
在对象内部状态改变时改变其行为。
package designModels;
public class TestState {
public static void main(String args[]) {
Girl girl = new Girl();
girl.setState(new HappyState());
girl.cry();
girl.smile();
girl.setState(new SadState());
girl.cry();
girl.smile();
}
}
class Girl {
private State state;
public void setState(State state) {
this.state = state;
}
public void cry() {
state.cry();
}
public void smile() {
state.smile();
}
}
abstract class State {
public abstract void cry();
public abstract void smile();
}
class HappyState extends State {
public void cry() {
System.out.println("高兴得哭了");
}
public void smile() {
System.out.println("高兴的笑了");
}
}
class SadState extends State {
public void cry() {
System.out.println("伤心的哭了");
}
public void smile() {
System.out.println("伤心地傻笑了");
}
}
--------------------------注:从此线往下的方法多数为借鉴前辈的程序,做了一些精简化的修改,用较少的代码说清楚问题-----------------------
10、模板方法(Template Method)
准备一个抽象类,把部分确定的逻辑定义在某些方法中,用其他抽象方法实现剩余的逻辑。不同子类对这些逻辑有不同的实现。 用法:定义多个抽象操作,定义并实现一个模板方法,将步骤放在这个具体方法里,推迟到子类实现。子类可以改变父类的可变部分,但不能改变模板方法所代表的顶级逻辑。
package designModels;
public class TestTemplateMethod {
public static void main(String[] args) {
XiaoPin xp = new DaPuKe();
xp.act();
}
}
abstract class XiaoPin {
public abstract void xuShi();
public abstract void gaoXiao();
public abstract void shanQing();
public final void act() {
xuShi();
gaoXiao();
shanQing();
}
}
class DaPuKe extends XiaoPin {
public void xuShi() {
System.out.println("火车除夕,老同学见面");
}
public void gaoXiao() {
System.out.println("名片当作扑克");
}
public void shanQing() {
System.out.println("马家军");
}
}
11、备忘录模式(Memento)
备忘录的角色
发起人Originator:创建含有内部状态的备忘录对象,并使用备忘录对象存储状态
负责人Caretaker:负责人保存备忘录对象,但不检查备忘录对象的内容
备忘录Memento :备忘录对象将发起人对象的内部状态存起来,并保正其内容不被发起人对象之外的对象像读取
窄接口(黑箱)模式:在备忘录的角色中,定义了他必须对不同的人提供不同的接口,对发起人提供宽接口,对其它任何人提供窄接口
宽接口(白箱)模式:都提供宽接口,安全性不够好。
package designModels;
public class TestMemento {
public static void main(String[] args) {
Originator o = new Originator();
Caretaker c = new Caretaker();
// use wide interface
o.setState("On");
c.saveMemento(o.createMemento());
o.setState("Off");
o.restoreMemento(c.retrieveMemento());
System.out.println(o.getState());
// use narrow interface
NarrowMemento memento = o.getNarrowMemento();
memento.narrowMethod();
}
}
interface NarrowMemento {
public void narrowMethod();
}
class Originator {
private String state;
private Memento memento;
public NarrowMemento createMemento() {
memento = new Memento();
memento.setState(this.state);
return memento;
}
public void restoreMemento(NarrowMemento memento) {
Memento aMemento = (Memento) memento;
this.setState(aMemento.getState());
}
public String getState() {
return this.state;
}
public void setState(String state) {
this.state = state;
}
// 内部类
protected class Memento implements NarrowMemento {
private String savedState;
private Memento() {
}
private void setState(String someState) {
savedState = someState;
}
private String getState() {
return savedState;
}
public void narrowMethod() {
System.out.println("this is narrow method");
}
}
public NarrowMemento getNarrowMemento() {
return memento;
}
}
class Caretaker {
private NarrowMemento memento;
public NarrowMemento retrieveMemento() {
return this.memento;
}
public void saveMemento(NarrowMemento memento) {
this.memento = memento;
}
}
12、门面模式(Fasade)
门面模式为了系统提供一个 统一的高层接口供外部客户使用。也是提供一个更高的层次的接口,使得子系统更容易使用。
门面模式实现形式:
◇定义一个(或多个)具备所需接口的新类(门面类)
◇新类门户使用原来的系统
◇客户使用门面类对象与原系统打交道
13、建造模式(Builder)
建造模式将一个产品的内部表象与产品生成过程分割出来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。
i)抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的构造;
ii)具体建造者(ConcretBuilder)角色:它在应用程序的调用下创建产品的实例。完成任务为;
a) 实现抽象建造者Builder接口,给出一步步完成创建产品实例的操作;
b) 在创建完成后,提供产品的实例。
iii) 导演者(Director角色):调用具体建造者角色以创建产品对象;
iv)产品(Product)角色:建造中的复杂对象。一般情况下,一个系统不止一个产品类。
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestBuilder {
public static void main(String args[]) {
Director director = new Director();
Builder bigBuilder = new BigHouseBuilder();
director.build(bigBuilder);
Product product = bigBuilder.getResult();
product.show();
Builder smallBuilder = new SmallHouseBuilder();
director.build(smallBuilder);
product = smallBuilder.getResult();
product.show();
}
}
class Product {
private List<String> parts = new ArrayList<String>();
public void addParts(String s) {
this.parts.add(s);
}
public void show() {
for (String s : parts) {
System.out.println(s);
}
}
}
class Director {
public void build(Builder builder) {
builder.BuildDoor();
builder.BuildWindow();
}
}
interface Builder {
public void BuildDoor();
public void BuildWindow();
public Product getResult();
}
class BigHouseBuilder implements Builder {
private Product product = new Product();
public void BuildDoor() {
product.addParts("Big Door");
}
public void BuildWindow() {
product.addParts("Big Window");
}
public Product getResult() {
return product;
}
}
class SmallHouseBuilder implements Builder {
private Product product = new Product();
public void BuildDoor() {
product.addParts("Small Door");
}
public void BuildWindow() {
product.addParts("Small Window");
}
public Product getResult() {
return product;
}
}
14、原型模式(ProtoType)
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
Java中要给出Clonable接口的实现,具体类要实现这个接口,并给出clone()方法的实现细节。
浅拷贝:只拷贝简单属性的值和对象属性的地址
深拷贝:拷贝本对象引用的对象,有可能会出现循环引用的情况。可以用串行化解决深拷贝。写到流里再读出来,这时会是一个对象的深拷贝结果。
package designModels;
import java.io.*;
public class TestPrototype {
public static void main(String args[]) throws CloneNotSupportedException {
ConcretePrototype c1 = new ConcretePrototype();
TestClass test = new TestClass();
test.setS("123");
c1.setI(1);
c1.setTestClass(test);
c1.show();
ConcretePrototype c2 = (ConcretePrototype) c1.Clone();
test = c2.getTestClass();
test.setS("456");
c2.setTestClass(test);
c2.setI(2);
c2.show();
c1.show(); //深复制这里输出 123 , 浅复制这里输出 456
}
}
/**
* 用于测试深复制和浅复制的类
* 需要实现Serializable接口
* @author YangYi
*/
class TestClass implements Serializable {
private String s;
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
class ConcretePrototype extends Prototype {
public void show() {
System.out.println(this.getI());
System.out.println(this.getTestClass().getS());
}
}
class Prototype implements Cloneable, Serializable {
private int i;
private TestClass testClass;
/**
* 此为浅复制
* @return
*/
/*public Object Clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return null;
}*/
/**
* 此为深复制
* @return
*/
public Object Clone() throws CloneNotSupportedException {
ByteArrayOutputStream bo = null;
ObjectOutputStream oo = null;
ByteArrayInputStream bi = null;
ObjectInputStream oi = null;
try {
bo = new ByteArrayOutputStream();
oo = new ObjectOutputStream(bo);
oo.writeObject(this);
byte[] bytes = bo.toByteArray();
bi = new ByteArrayInputStream(bytes);
oi = new ObjectInputStream(bi);
return oi.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
bo.close();
oo.close();
bi.close();
oi.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public TestClass getTestClass() {
return testClass;
}
public void setTestClass(TestClass testClass) {
this.testClass = testClass;
}
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
}
15、适配器模式(Adapter)
适配就是由“被适配者”到“目标”的适配,而当中链接两者的关系就是适配器。它负责把“被适配者”过度到“目标”。
适配器一共包括3种角色
1、目标:目标是一个接口,该接口是客户想使用的接口
2、被适配者:被适配者是一个已存在的接口或抽象类,这个接口或抽象类需要适配
3、适配器:适配器是一个类,该类实现了目标接口并包含有被适配者的引用,即适配者的指着是对被适配者接口与目标进行适配
package designModels;
public class TestAdapter {
public static void main(String args[]) {
PC pc = new PC();
PS2 ps2 = new Adapter(new UsbMouse());
pc.useP2Mouse(ps2);
}
}
/**
* 源
* @author YangYi
*/
class PC {
public void useP2Mouse(PS2 ps2) {
ps2.useMouseByPS2();
}
}
interface USB {
public void useMouseByUSB();
}
interface PS2 {
public void useMouseByPS2();
}
/**
* 目标
* @author YangYi
*/
class UsbMouse implements USB {
public void useMouseByUSB() {
System.out.println("USB Mouse is working");
}
}
/**
* 适配器
* @author YangYi
*/
class Adapter implements PS2 {
private USB usb;
public Adapter(USB usb) {
this.usb = usb;
}
public void useMouseByPS2() {
System.out.println("Adapter is working");
usb.useMouseByUSB();
}
}
16、组合模式(Composite)
将对象以树形结构组织起来,以达成“部分-整体”的层次结构,使得客户端对单个对象和组合对象的使用具有一致性。
在设计中想表示对象的“部分-整体”层次结构;希望用户忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象。
1) 抽象构件角色Component:它为组合中的对象声明接口,也可以为共有接口实现缺省行为。
2) 树叶构件角色Leaf:在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。
3) 树枝构件角色Composite:在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口;存储子部件。
一个Composite实例可以像一个简单的Leaf实例一样,可以把它传递给任何使用Component的方法或者对象,并且它表现的就像是一个Leaf一样。
以文件和文件夹拷贝为例:
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestComposite {
public static void main(String[] args) {
Node file1 = new File("file1");
Node file2 = new File("file2");
Node file3 = new File("file3");
Node file4 = new File("file4");
Node floder1 = new Floder("floder1");
Node floder2 = new Floder("floder2");
Node MyComputer = new Floder("MyComputer");
MyComputer.addNode(floder1);
floder1.addNode(file2);
floder2.addNode(file3);
floder2.addNode(file4);
floder1.addNode(file1);
MyComputer.addNode(floder2);
MyComputer.copy();
}
}
abstract class Node {
protected List<Node> nodes = new ArrayList<Node>();
public abstract void copy();
public abstract void addNode(Node node);
public abstract void setLevel(int level);
public abstract void adjustLevel(Node node);
}
class File extends Node {
private String name;
private int level = 1;
public File(String name) {
this.name = name;
}
public void copy() {
for (int i = 0; i < this.level; i++)
System.out.print("---");
System.out.println(this.name + " is copyed");
}
public void setLevel(int level) {
this.level = level;
}
public void adjustLevel(Node node) {}
public void addNode(Node node) {}
}
class Floder extends Node {
private String name;
private int level = 1;
public Floder(String name) {
this.name = name;
}
public void addNode(Node node) {
this.nodes.add(node);
adjustLevel(node);
}
public void adjustLevel(Node node) {
node.setLevel(this.level + 1);
for (Node n : node.nodes) {
node.adjustLevel(n);
}
}
public void copy() {
for (int i = 0; i < this.level; i++)
System.out.print("---");
System.out.println(this.name + " is copyed");
for (Node node : nodes) {
node.copy();
}
}
public void setLevel(int level) {
this.level = level;
}
}
简化的一个版本,只说明composite模式,去掉Level的计算
package designModels;
import java.util.ArrayList;
import java.util.List;
public class TestComposite2 {
public static void main(String[] args) {
Node file1 = new File("file1");
Node file2 = new File("file2");
Node file3 = new File("file3");
Node file4 = new File("file4");
Node floder1 = new Floder("floder1");
Node floder2 = new Floder("floder2");
Node MyComputer = new Floder("MyComputer");
MyComputer.addNode(floder1);
floder1.addNode(file1);
floder1.addNode(file2);
floder2.addNode(file3);
floder2.addNode(file4);
MyComputer.addNode(floder2);
MyComputer.copy();
}
}
interface Node {
public abstract void copy();
public abstract void addNode(Node node);
}
class File implements Node {
private String name;
public File(String name) {
this.name = name;
}
public void copy() {
System.out.println(this.name + " is copyed");
}
public void addNode(Node node) {
}
}
class Floder implements Node {
protected List<Node> nodes = new ArrayList<Node>();
private String name;
public Floder(String name) {
this.name = name;
}
public void addNode(Node node) {
this.nodes.add(node);
}
public void copy() {
System.out.println(this.name + " is copyed");
for (Node node : nodes) {
node.copy();
}
}
}
17、装饰模式(Decorator)
装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。
装饰器模式具有如下的特征:
它必须具有一个装饰的对象。
它必须拥有与被装饰对象相同的接口。
它可以给被装饰对象添加额外的功能。
用一句话总结就是:保持接口,增强功能。
装饰器通过包装一个装饰对象来扩展其功能,而又不改变其接口,这实际上是基于对象的适配器模式的一种变种。它与对象的适配器模式的异同点如下。
相同点:都拥有一个目标对象。
不同点:适配器模式需要实现另外一个接口,而装饰器模式必须实现该对象的接口。
以一个礼物为例,送一束花Flower,价格2元
使用装饰器,在花上面加一个祝福卡片,得到装饰后的礼物和价格
package designModels;
public class TestDecorator {
public static void main(String args[]) {
Gift gift = new Flower();
Gift flowerAndCard = new FlowerAndCard(gift);
System.out.println(flowerAndCard.getCost());
}
}
interface Gift {
public double getCost();
}
class Flower implements Gift {
public double getCost() {
return 2.0;
}
}
abstract class Decorator implements Gift {
Gift gift;
public abstract double getCost();
}
class FlowerAndCard extends Decorator {
public FlowerAndCard(Gift gift) {
this.gift = gift;
}
@Override
public double getCost() {
return gift.getCost() + 0.5;
}
}
18、代理模式(Proxy)
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
一般涉及到的角色有:
抽象角色:声明真实对象和代理对象的共同接口;
代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
在动态代理中:
Java动态代理类位于Java.lang.reflect包下,一般主要涉及到以下两个类:
(1). Interface InvocationHandler:该接口中仅定义了一个方法Object:invoke(Object obj,Method method, Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组。这个抽象方法在代理类中动态实现。
(2).Proxy:该类即为动态代理类,作用类似于上例中的ProxySubject,其中主要包含以下内容:
Protected Proxy(InvocationHandler h):构造函数,估计用于给内部的h赋值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。
所谓Dynamic Proxy是这样一种class:它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。
package designModels;
import java.lang.reflect.*;
public class TestProxy {
public static void main(String args[]) {
TestIF testIF = new Test();
MyProxy myProxy = new MyProxy(testIF);
TestIF t = (TestIF) Proxy.newProxyInstance(testIF.getClass()
.getClassLoader(), testIF.getClass().getInterfaces(), myProxy);
t.method1();
t.method2();
}
}
interface TestIF {
public void method1();
public void method2();
}
class Test implements TestIF {
public void method1() {
System.out.println("Method 1 work!");
}
public void method2() {
System.out.println("Method 2 work!");
}
}
class MyProxy implements InvocationHandler {
private TestIF testIF;
public MyProxy(TestIF testIF) {
this.testIF = testIF;
}
public Object invoke(Object obj,Method method,Object[] args) throws Exception{
Object o;
System.out.println("Before method invoked!");
o = method.invoke(testIF, args);
System.out.println("After method invoked!");
return o;
}
}
19、享元模式(Flyweight)
享元模式是对象的结构模式,享元模式以共享的方式高效地支持大量的细粒度对象。
享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。
一个内蕴状态是存储在享元对象内部的,并且是不会随环境改变而有所不同的。因此,一个享元可以具有内蕴状态并可以共享。
一个外蕴状态是随环境改变而改变的、不可共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。
外蕴状态不可以影响享元对象的内蕴状态。换句话说,它们是相互独立的。
20、解释器模式(Interpreter)
解释器模式的定义如下:定义语言的文法,并且建立一个解释器来解释该语言中的句子。它属于类的行为模式。这里的语言意思是使用规定格式和语法的代码。
在GOF的书中指出:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。而且当文法简单、效率不是关键问题的时候效果最好。
21、迭代器模式(Iterator)
GOF给出的定义为:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节。
22、中介者模式(Mediator)
GOF给中介者模式下的定义是:用一个中介对象来封装一系列的对象交互。
中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。简单点来说,将原来两个直接引用或者依赖的对象拆开,在中间加入一个“中介”对象,使得两头的对象分别和“中介”对象引用或者依赖。
举一个例子,一项目工作需要轮翻工作,需要一个管理者(中介)统一调度,由管理者(中介)统一发布工作命令,不能由工人之间相互发布指令。
23、访问者模式(Visitor)
Java的Collection(包括Vector和Hashtable)是我们最经常使用的技术,可是Collection好象是个黑色大染缸,本来有各种鲜明类型特征的对象一旦放入后,再取出时,这些类型就消失了.那么我们势必要用If来判断.
很显然,这样做的缺点代码If else if 很繁琐.我们就可以使用Visitor模式解决它.
package designModels;
import java.util.*;
public class TestVisitor {
public static void main(String args[]){
Visitor visitor = new ConcreteVisitor();
StringElement stringE = new StringElement("I am a String");
visitor.visitString(stringE);
Collection list = new ArrayList();
list.add(new StringElement("I am a String1"));
list.add(new StringElement("I am a String2"));
list.add(new FloatElement(new Float(12)));
list.add(new StringElement("I am a String3"));
visitor.visitCollection(list);
}
}
interface Visitable {
public void accept(Visitor visitor);
}
interface Visitor {
public void visitString(StringElement stringE);
public void visitFloat(FloatElement floatE);
public void visitCollection(Collection collection);
}
class StringElement implements Visitable {
private String value;
public StringElement(String string) {
value = string;
}
public String getValue() {
return value;
}
// 定义accept的具体内容 这里是很简单的一句调用
public void accept(Visitor visitor) {
visitor.visitString(this);
}
}
class FloatElement implements Visitable {
private Float value;
public FloatElement(Float value) {
this.value = value;
}
public Float getValue() {
return value;
}
// 定义accept的具体内容 这里是很简单的一句调用
public void accept(Visitor visitor) {
visitor.visitFloat(this);
}
}
class ConcreteVisitor implements Visitor {
// 在本方法中,我们实现了对Collection的元素的成功访问
public void visitCollection(Collection collection) {
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
Object o = iterator.next();
if (o instanceof Visitable)
((Visitable) o).accept(this);
}
}
public void visitString(StringElement stringE) {
System.out.println("'" + stringE.getValue() + "'");
}
public void visitFloat(FloatElement floatE) {
System.out.println(floatE.getValue().toString() + "f");
}
}