各种博客复制而来并整理。故无法给出所有原文链接。


==================================



一、迭代器模式

提供一种方法访问一个容器(container)对象中的各个元素,而又不暴露该对象的内部细节。

类图:


用法:

public interface Iterator
{
    public Object first();

    public Object next();

    public Object currentItem();

    public boolean isDone();
}

public class ConcreteIterator implements Iterator
{
    private int currentIndex = 0;
    private Vector vector = null;

    public ConcreteIterator(final Vector vector)
    {
        this.vector = vector;
    }

    @Override
    public Object first()
    {
        currentIndex = 0;
        return vector.get(currentIndex);
    }

    @Override
    public Object next()
    {
        currentIndex++;
        return vector.get(currentIndex);
    }

    @Override
    public Object currentItem()
    {
        return vector.get(currentIndex);
    }

    @Override
    public boolean isDone()
    {
        if (currentIndex >= this.vector.size() - 1)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

public interface Aggregat
{
    public Iterator createIterator();
}

public class ConcreteAggregat implements Aggregat
{
    private Vector vector = null;

    public Vector getVector()
    {
        return vector;
    }

    public void setVector(final Vector vector)
    {
        this.vector = vector;
    }

    public ConcreteAggregat()
    {
        vector = new Vector();
        vector.add("vector 1");
        vector.add("vector 2");
    }

    @Override
    public Iterator createIterator()
    {
        return new ConcreteIterator(vector);
    }
}

public class Client
{
    public static void main(final String[] args)
    {
        final Aggregat agg = new ConcreteAggregat();
        final Iterator iterator = agg.createIterator();
        System.out.println(iterator.first());
        while (!iterator.isDone())
        {
            System.out.println(iterator.next());
        }
    }
}

结果:
vector 1
vector 2



二、代理模式

为另一个对象提供一个替身或占位符以控制对这个对象的访问,简而言之就是用一个对象来代表另一个对象。

类图:



简单例子:有个接口Italk,people对象实现这个接口的talk()方法,有些想另外加入sing()方法,所以增加代理类talkProxy,实现两个方法.
public interface ITalk
{
    public void talk(String msg);
}

public class People implements ITalk
{
    @Override
    public void talk(final String msg)
    {
        System.out.println(msg);
    }
}

public class TalkProxy implements ITalk
{
    ITalk italk;

    public TalkProxy(final ITalk italk)
    {
        this.italk = italk;
    }

    @Override
    public void talk(final String msg)
    {
        this.italk.talk(msg);
    }

    public void sing(final String songName)
    {
        System.out.println("Song Name:" + songName);
    }
}

public class Client
{
    public static void main(final String[] args)
    {
        People people = new People();
        people.talk("I can't sing");

        TalkProxy proxy = new TalkProxy(people);
        proxy.talk("I can talk");
        proxy.sing("I can sing");
    }
}

结果:
I can't sing
I can talk
Song Name:I can sing


三、原型模式

原型模式是一种创建型设计模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的.
原型模式多用于创建复杂的或者耗时的实例, 因为这种情况下,复制一个已经存在的实例可以使程序运行更高效,或者创建值相等,只是命名不一样的同类数据.

原型模式中的拷贝分为"浅拷贝"和"深拷贝":
浅拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象.
深拷贝: 对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制.


 类图: 


 涉及到三个角色:

  (1)客户(Client)角色:客户类提出创建对象的请求。

  (2)抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。

  (3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。

源代码

  抽象原型角色

复制代码
public interface Prototype{     /**      * 克隆自身的方法      * @return 一个从自身克隆出来的对象      */     public Object clone(); }
复制代码

  具体原型角色

复制代码
public class ConcretePrototype1 implements Prototype {     public Prototype clone(){         //最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了         Prototype prototype = new ConcretePrototype1();         return prototype;     } }
复制代码
复制代码
public class ConcretePrototype2 implements Prototype {     public Prototype clone(){         //最简单的克隆,新建一个自身对象,由于没有属性就不再复制值了         Prototype prototype = new ConcretePrototype2();         return prototype;     } }
复制代码

  客户端角色

复制代码
public class Client {     /**      * 持有需要使用的原型接口对象      */     private Prototype prototype;     /**      * 构造方法,传入需要使用的原型接口对象      */     public Client(Prototype prototype){         this.prototype = prototype;     }     public void operation(Prototype example){         //需要创建原型接口的对象         Prototype copyPrototype = prototype.clone();              } }
复制代码


四、装饰模式

装饰模式是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰模式的特点:
1) 装饰对象和真实对象有相同的接口,这样客户端对象就可以和真实对象相同的方式和装饰对象交互。
2)装饰对象包含一个真实对象的引用。
3)装饰对象接受所有来自客户端的请求,它把这些请求转发给真实的对象。
4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

类图:





实例:
public abstract class Drink
{
    protected String desc;

    public String getDesc()
    {
        return this.desc;
    }

    public abstract float cost();
}

public class Espresso extends Drink
{
    public Espresso()
    {
        this.desc = "in Espresso,";
    }

    @Override
    public float cost()
    {
        return 100;
    }
}

public class DartRoast extends Drink
{
    public DartRoast()
    {
        this.desc = "in DartRoast,";
    }

    @Override
    public float cost()
    {
        return 50;
    }
}

public abstract class Decorator extends Drink
{
    protected final Drink drink;

    public Decorator(final Drink drink)
    {
        this.drink = drink;
    }

    @Override
    public abstract float cost();
}

public class Mocha extends Decorator
{
    public Mocha(final Drink drink)
    {
        super(drink);
        this.desc = " add Mocha ";
    }

    @Override
    public String getDesc()
    {
        return this.drink.getDesc() + this.desc;
    }

    @Override
    public float cost()
    {
        return this.drink.cost() + 10;
    }
}

public class Soy extends Decorator
{
    public Soy(final Drink drink)
    {
        super(drink);
        this.desc = " add Soy ";
    }

    @Override
    public String getDesc()
    {
        return this.drink.getDesc() + this.desc;
    }

    @Override
    public float cost()
    {
        return this.drink.cost() + 5;
    }
}

public class Whip extends Decorator
{
    public Whip(final Drink drink)
    {
        super(drink);
        this.desc = " add Whip ";
    }

    @Override
    public String getDesc()
    {
        return this.drink.getDesc() + this.desc;
    }

    @Override
    public float cost()
    {
        return this.drink.cost() + 15;
    }
}

public class Client
{
    public static void main(final String[] args)
    {
        final Drink dartRoastDrink = new DartRoast();
        final Drink espressoDrink = new Espresso();

        final Drink Mocha = new Mocha(dartRoastDrink);
        final Drink soy = new Soy(Mocha);
        System.out.println(soy.getDesc() + soy.cost());

        final Drink whip = new Whip(espressoDrink);
        System.out.println(whip.getDesc() + whip.cost());
    }
}

结果:
in DartRoast, add Mocha  add Soy 65.0
in Espresso, add Whip 115.0

优点:
1)Decorator模式与继承关系的目的都是扩展对象功能,但是Decorator可以提供比继承更多的灵活性。
2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

缺点:
1)这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2)装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否适合。当然也可以改变Component接口,增加新的公开的行为,实现"半透明"的装饰者模式。在实际项目中要做出最佳选择。

在java类库中的IO流就是用装饰者模式设计的。




五、外观模式


外观模式为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用。他是为子系统中的一组接口所提供的一个一致的界面。

它与Adapter和Proxy有类似之处,但是Proxy注重在为Client-Subject提供一个访问的中间层,Adapter注重对接口的转换与调整,而Facade所面对的往往是多个类或其他程序单元,通过重新组合各类及程序单元,对外提供统一的接口/界面。

在遇到以下情况使用Facade模式:
1. 当你要为一个复杂子系统提供一个简单接口时。
2. 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入Facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
3. 当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点,如果子系统之间是相互依赖的,你可以让他们仅通过Facade进行通讯,从而简化了他们之间的依赖关系。

优点:
1. 它对客户屏蔽子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便。
2. 它实现了子系统与客户之间的松耦合关系,而子系统内部的功能组件往往是紧耦合的。
3. 如果应用需要,它并不限制他们使用子系统类。因此你可以在系统易用性和通用性之间加以选择。




六、策略模式

类图:




在策略模式中, 使用的是“聚合”而不是 “关联”关系!



策略模式的组成:
抽象策略角色:策略类,通常由一个接口或者抽象类实现。
具体策略角色:包装了相关的算法和行为。
环境角色:持有一个策略类的引用,最终给客户端调用。

实例:一网站对所有高级会员提供30%的折扣,对中级会员提供20%的折扣,初级会员10%的折扣,非会员没有折扣
public interface MemberStrategy
{
    public double discount();
}

public class PrimaryMember implements MemberStrategy
{
    @Override
    public double discount()
    {
        return 0.1;
    }
}

public class IntermediateMember implements MemberStrategy
{
    @Override
    public double discount()
    {
        return 0.2;
    }
}

public class AdvancedMember implements MemberStrategy
{
    @Override
    public double discount()
    {
        return 0.3;
    }
}

public class MemberContext
{
    private MemberStrategy memberStrategy = null;

    public MemberContext(final MemberStrategy memberStrategy)
    {
        this.memberStrategy = memberStrategy;
    }

    public double discount()
    {
        return this.memberStrategy.discount();
    }
}