各种博客复制而来并整理。故无法给出所有原文链接。
==================================
一、迭代器模式
提供一种方法访问一个容器(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();
}
}
转载于:https://blog.51cto.com/hyman1994/1663641