??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
]]>
public class Singleton {
private static Singleton instance;
private Singleton(){
}
public static Singleton getInstance(){
if(instance==null)
instance=new Singleton();
return instance;
}
}
q个E序在单U程下运行不?x)有问题Q但是它不能q行在多U程的环境下Q若惌q行在多U程的环境下Q必M改如下:(x)
public class Singleton {
private static class Instance{
static final Singleton instance=new Singleton();
}
private Singleton(){
}
public static Singleton getInstance(){
return Instance.instance;
}
}
q样做之所以可以,是因为静态的内部cInstance只会(x)被装载一ơ。运行在多线E下的单态设计模式也叫Double-Checked Looking模式?br />
]]>
abstract class QueryTemplate{
public void doQuery(){ //Template Method
formatConnect();
formatSelect();
}
protected abstract void formatConnect();
protected abstract void formatSelect();
}
class OracleQT extends QueryTemplate{
public void formatConnect() {
System.out.println("格式化Qracle数据库连?);
}
public void formatSelect() {
System.out.println("格式化Oracle数据库查?);
}
}
class MysqlQT extends QueryTemplate{
public void formatConnect() {
System.out.println("格式化Mysql数据库连?);
}
public void formatSelect() {
System.out.println("格式化Mysql数据库查?);
}
}
public class client {
public static void main(String[] args) {
QueryTemplate oracleQT=new OracleQT();
oracleQT.doQuery();
QueryTemplate mysqlQT=new MysqlQT();
mysqlQT.doQuery();
}
}
输出l果Q?br />
格式化Qracle数据库连?br />
格式化Oracle数据库查?br />
格式化Mysql数据库连?br />
格式化Mysql数据库查?br />
在这个例子中Q我们定义了一个骨架QueryTemplateQ在它的内部定义了一个Template Method,和一些步骤(抽象Ҏ(gu)Q?使用Template Method来调用这些步骤。步骤是在子cM实现的?br />
结:有时候,?x)遇到由一pd步骤构成的过E需要执行。这个过E从高层ơ上看是相同的,但有些步骤的实现可能不同。正如,查询SQL数据库从高层ơ上看过E是相同的,但某些细节比如如何连接数据库则可能因q_{细节的不同而不同。通过Template Method模式Q我们可以先定义步骤序列Q然后覆盖那些需要改变的步骤?/p>
]]>
import java.util.Vector;
class Children{
static private Vector<Observer> obs;
static private String state=null;
static{
obs=new Vector<Observer>();
}
public static void attach(Observer o){
obs.addElement(o);
}
public static void detach(Observer o){
obs.removeElement(o);
}
public void setState(String str){
state=str;
}
public String getState(){
return state;
}
public void notifyObs(){
for(Observer o:obs){
o.update(this);
}
}
}
interface Observer{
public void update(Children child);
}
class Parent implements Observer{
public void update(Children child){
if(child.getState().equals("fight")){
System.out.println("ParentQ他和别人打架了");
}else if(child.getState().equals("scholarship")){
System.out.println("告诉Parent,他得C奖学?);
}
}
}
class Mother implements Observer{
public void update(Children child){
if(child.getState().equals("fight")){
System.out.println("告诉MotherQ他和别人打架了");
}else if(child.getState().equals("scholarship")){
System.out.println("告诉Mother,他得C奖学?);
}
}
}
public class Client {
public static void main(String[] args) {
Children child=new Children();
Observer parent=new Parent();
Observer mother=new Mother();
child.attach(parent);
child.attach(mother);
child.setState("fight");
child.notifyObs();
child.setState("scholarship");
child.notifyObs();
}
}
输出如下:
告诉ParentQ他和别人打架了
告诉MotherQ他和别人打架了
告诉Parent,他得C奖学?br />
告诉Mother,他得C奖学?br />
结Q对于Observer模式Q触发事件的对象-Subject对象无法预测可能需要知道该事g的所有对象。ؓ(f)了解册一问题Q我们创Z个Observer接口Q要求所有的Observer负责自己注册到Subject上?br />
代码如下Q?br />
abstract class Component{
abstract public void printTicket();
}
class SalesTicket extends Component{
public void printTicket() {
System.out.println("打印出salesTicket的内?);
}
}
abstract class TicketDecorator extends Component{
private Component myTrailer;
public TicketDecorator(Component myComponent){
myTrailer=myComponent;
}
public void callTrailer(){
if(myTrailer!=null)
myTrailer.printTicket();
}
}
class Header extends TicketDecorator{
public Header(Component myComponent){
super(myComponent);
}
public void printTicket(){
System.out.println("打印salesTicket的头信息");
super.callTrailer();
}
}
class Footer extends TicketDecorator{
public Footer(Component myComponent){
super(myComponent);
}
public void printTicket(){
super.callTrailer();
System.out.println("打印salesTicket的页脚信?);
}
}
public class Client {
public static void main(String[] args) {
System.out.println("====================================");
new Header(new Footer(new SalesTicket())).printTicket();
System.out.println("====================================");
new Footer(new Header(new SalesTicket())).printTicket();
System.out.println("====================================");
}
}
输出l果如下:
====================================
打印salesTicket的头信息
打印出salesTicket的内?br />
打印salesTicket的页脚信?br />
====================================
打印salesTicket的头信息
打印出salesTicket的内?br />
打印salesTicket的页脚信?br />
====================================
从这个例子我们可以看出,Decorator模式把问题分Z部分Q?br />
1Q?nbsp;如何实现提供新功能的对象?br />
2Q?nbsp;如何为每U特D情늻l对象?br />
q样能够Decorator对象的实C军_如何使用Decorator的对象分d来,从而提高了内聚性,因ؓ(f)每个Decorator对象只用兛_自己d的功能,无需兛_自己是如何被加入到对象链中。还可以L地重排Decorator的顺序,无需改变其Q何代码?br />
结QDecorator模式的适用场合是,各种可选的功能在另一个肯定要执行的功能之前或之后执行?/p>
为创Zl相x怺依赖的对象提供一个接口,而且无需指定它们的具体类?br />
大致意思是_(d)(x)我们在创些对象的时候,q不需要指定它们的具体c,q些具体cȝ对象是由工厂对象负责实例化的。下面是《Design Patterns Explained》一书的例子Q有兌机pȝ的显C和打印E序Q用来显C和打印的分辨率取决于当前运行的pȝ。低端机使用低分辨率的显C和打印驱动E序Q高端机使用高分辨率的显C和打印驱动E序。其l构囑֦下:(x)
代码如下:
abstract class ResFactory{
abstract public DisplayDriver getDisplayDrvr();
abstract public PrintDriver getPrintDrvr();
}
class LowResFact extends ResFactory{
public DisplayDriver getDisplayDrvr() {
returnnew LRDD();
}
public PrintDriver getPrintDrvr() {
returnnew LRPD();
}
}
class HighResFact extends ResFactory{
public DisplayDriver getDisplayDrvr() {
returnnew HRDD();
}
public PrintDriver getPrintDrvr() {
returnnew HRPD();
}
}
abstract class DisplayDriver{
}
abstract class PrintDriver{
}
class HRDD extends DisplayDriver{
public HRDD() {
System.out.println("使用高端机的昄驱动E序")
}
}
class LRDD extends DisplayDriver{
public LRDD(){
System.out.println("使用低端机的昄驱动E序");
}
}
class HRPD extends PrintDriver{
public HRPD() {
System.out.println("使用高端机的打印驱动E序");
}
}
class LRPD extends PrintDriver{
public LRPD() {
System.out.println("使用低端机的打印驱动E序");
}
}
public class ApControl {
public static ResFactory getResFactory(ResFactory factory){
return factory;
}
public static void main(String[] args) {
ResFactory highResFact=ApControl.getResFactory(new HighResFact());
highResFact.getDisplayDrvr();
highResFact.getPrintDrvr();
ResFactory lowResFact=ApControl.getResFactory(new LowResFact());
lowResFact.getDisplayDrvr();
lowResFact.getPrintDrvr();
}
}输出l果Q?/span>
使用高端机的昄驱动E序
使用高端机的打印驱动E序
使用低端机的昄驱动E序
使用低端机的打印驱动E序
在这个例子中ApControl使用z自两个不同的服务c?DisplayDriver和PrintDriver)的对象。这个设计非常简化,隐藏了实现细节,pȝ的可l护性也更好。ApControl不知道自己拥有的服务对象的那个特定具体实玎ͼ因ؓ(f)创徏对象是工厂的职责。ApControl也不知道自己使用的是哪个特定工厂Q因为它只知道自己有一个ResFactory对象。它可能是一个HighResFact也可能是一个LowResFactQ但它不知道到底是哪一个?/span>
结Q在必须协调一l对象的创徏Ӟ可以应用Abstract Factory模式。它提供了一U方式,如何执行对象实例化的规则从使用q些对象的客户对象中提取出来。首先,扑և实例化的规则Q定义了一个带接口的抽象类Q其中的接口为每U需要实例化的对象提供一个方法。然后,从这个类为每个组实现具体cR最后,由客户对象决定用具体工厂来创徏所需的对象。它主要适用于以下几U情?
1) 一个系l要独立于它的品的创徏、组合和表示时?/span>
2) 可以对系l进行配|,以便pȝ可以使用多个产品pd中的某一个?/span>
3) 当需要强调一pd相关产品对象的设计以便进行联合用时?/span>
4) 当希望提供一个品类库,而只xCZ们的接口而不是实现时?/span>
抽象与其实现解耦,使它们都可以独立地变化?/span>
大致意思是_(d)(x)一l实C另一l用他们的对象分离。这里的实现指的是抽象类?qing)?/span>
zcȝ来实现自q对象Q而不是抽象类的派生类Q这些派生类被称为具体类Q。下?/span>
是《Design Patterns Explained》书中的例子。其l构囑֦下:(x)
下面是它的实玎ͼ(x)
abstract class Shape{
protected Drawing myDrawing;
abstract public void draw();
Shape(Drawing drawing){
myDrawing=drawing;
}
protected void drawLine(){
myDrawing.drawLine();
}
protected void drawCircle(){
myDrawing.drawCircle();
}
}
class Rectangle extends Shape{
public Rectangle(Drawing darw){
super(darw);
}
public void draw(){
drawLine();
drawLine();
drawLine();
drawLine();
}
}
class Circle extends Shape{
public Circle(Drawing draw){
super(draw);
}
publicvoid draw(){
myDrawing.drawCircle();
}
}
abstract class Drawing{
abstract public void drawLine();
abstract public void drawCircle();
}
class V1Drawing extends Drawing{
public void drawLine(){
DP1.draw_a_line();
}
public void drawCircle(){
DP1.draw_a_circle();
}
}
class V2Drawing extends Drawing{
public void drawLine(){
DP2.drawLine();
}
public void drawCircle(){
DP2.drawCircle();
}
}
class DP1{
public static void draw_a_line(){
System.out.println("使用DP1的draw_a_line()ȝ");
}
public static void draw_a_circle(){
System.out.println("使用DP1的draw_a_circle()d");
}
}
class DP2{
public static void drawLine(){
System.out.println("使用DP2的drawLine()ȝ");
}
public static void drawCircle(){
System.out.println("使用DP2的drawCircle()d");
}
}
public class BridgeClient {
public static void main(String[] args) {
Drawing draw1=new V1Drawing();
Drawing draw2=new V2Drawing();
Shape shape1=new Rectangle(draw1);
shape1.draw();
Shape shape2=new Circle(draw2);
shape2.draw();
}
}
输出l果如下Q?/span>
使用DP1?/span>draw_a_line()ȝ
使用DP1?/span>draw_a_line()ȝ
使用DP1?/span>draw_a_line()ȝ
使用DP1?/span>draw_a_line()ȝ
使用DP2?/span>drawCircle()d
在这个例子中Shape对象实际上是一?/span>Retangle?/span>Circle对象Q?/span>?/span>Clientq不知道到底是那?/span>Q?/span>因ؓ(f)它们看v来都一栗?/span>Drawing实际上是一?/span>V1Drawing?/span>V2Drawing,?/span>Shape对象q知道到底是哪个Q?/span>因ؓ(f)它们看v来都一栗DP1或DP2使用它的Drawing对象知道是哪一个。Shape是事物的抽象QDrawing是实现或者操作事物方法的抽象。他们两个都可以独立地变化。正如例子中所说那P我们可以输出一个矩形可以用V1Drawing也可以用V2Drawing来完成,输出一个圆形也是一样都有两U方法。Bridge模式遵@了设计模式中两条基本{略Q找出变化ƈ装之和优先使用对象聚集Q而不是类l承?/span>
结QBridge模式是一U抽象与其实现相分离的模式。它主要应用于:(x)当事物是一l变化量Q和对这些事物的操作Ҏ(gu)(实现)也是一l变化量的情况,也就是说它们都是多变的?/span>
定义一pd的算法,把他们一个个装hQƈ且它们可相互替换。Strategy模式使算法可独立于用它的客戯变化?/span>
Strategy模式以下列几条原则ؓ(f)基础Q?/span>
1Q?nbsp;每个对象都是一个具有职责的个体?/span>
2Q?nbsp;q些职责不同的具体实现是通过多态的使用来完成的?/span>
3Q?nbsp;概念上相同的法h多个不同的实玎ͼ需要进行管理?/span>
下面我将通过一个实例来说明它的具体使用Q这个例子是关于数据库连接的。代码如下:(x)
interface DatabaseStrategy{
public void process();
}
class MysqlDBStrategy implements DatabaseStrategy{
public void process() {
System.out.println("处理Mysql数据库连?/span>");
}
}
class OracleDBStrategy implements DatabaseStrategy{
public void process() {
System.out.println("处理Oracle数据库连?/span>");
}
}
class DataBaseManager{
public void process(DatabaseStrategy dbStrategy){
dbStrategy.process();
}
}
publicclass StrategyClient {
public static void main(String[] args) {
MysqlDBStrategy mysql=new MysqlDBStrategy();
DataBaseManager manager=new DataBaseManager();
manager.process(mysql);
OracleDBStrategy oracle=new OracleDBStrategy();
manager.process(oracle);
}
}
在我们的实际~程中经怼(x)遇到pȝ要连接的数据库可能不只一U,如果采用传统的方法,即修改连接Url的方法,q种Ҏ(gu)实可行Q但是有一个问题要l常修改源代码,不利于以后的l护Q那么有没有一U更好的Ҏ(gu)呢?{案是有Q用Strategy模式Q首先定义一个连接数据库通用的接口(在上面的例子中是DatabaseStrategyQ?然后再定义实现该接口的具体类(MysqlDBStrategy、OracleDBStrategy)Q在q些具体c,实现具体的逻辑。最后再定义一个管理数据库q接的类(DataBaseManager),它的内部有一个方法可以接受具体类实例的参数。我们可以看到这个参数是DatabaseStrategycd的,也就是说它可以接受Q何一个实CDatabaseStrategy接口的类的具体实例(q里q用了对象替换机Ӟ多态的一U)Q从而完成数据库q接的处理。如果我们还需要处理另外一U数据库如sqlserverQ我们只需要徏立一个SqlserverDBStrategycd现DatabaseStrategy接口Q把该类的实例传lDatabaseManager的processҎ(gu)卛_?/span>
结QStrategy模式是一U定义一pd法的方法。概念上看,q些法完成的都是相同的工作Q只是实C同?/span>q段话大致是_(d)(x)我们需要一U方式,Z个功能正但接口不合的对象创Z个新接口。例如,客户l我们如下需求:(x)
1Q?nbsp;为都?#8220;昄”(display)行ؓ(f)的点、线、正方Ş分别创徏cR?/span>
2Q?nbsp;客户对象不必知道自己到底拥有炏V线、还是正方Ş。它只需知道拥有q些形状中的一个?/span>
也就是说Q我们要用一个更高层ơ的概念这些具体Ş犉늛q去Q这个高层概念可以称为:(x)“可显C的形状”。因此,我们需要创Z个接口Shape:
interface Shape{
publicvoid display();
}
现在客户忽然间有让我们给q个pȝ增加一个画圆的功能。这个看h很简单,只需定义一?/span>CirclecL实现Shape接口Q但是我们要l它~写displayҎ(gu)Q这可不是g单的事,假如此时我们正好发现一?/span>XXCirclec,它有一个方法刚好可以完成这个功能,那么有没有更好的Ҏ(gu)来利用它呢,q时我们p用到Adapter模式了?/span>XXCircle代码如下Q?/span>
class XXCircle{
public void displayCircle(){
System.out.println("通过XXCircle.displayCircle()d");
}
}
Adapter模式有两U类型:(x)
1) 对象Adapter模式Q它依赖于一个对象(适配器)包含另一个对?/span>(被适配的对?/span>)?/span>
class CircleObject implements Shape{
public XXCircle circle;
public CircleObject(XXCircle xxcircle){
circle=xxcircle;
}
public void display() {
circle.displayCircle();
}
}
public class Client {
public static void main(String[] args) {
XXCircle circle=new XXCircle();
CircleObject co=new CircleObject(circle);
co.display();
}
}
2) cAdapter模式Q它是通过多重l承来实现的Qjava中没有多l承Q是通过接口来实现的Q?/span>
class CircleClass extends XXCircle implements Shape{
public void display() {
super.displayCircle();
}
}
public class Client {
public static void main(String[] args) {
CircleClass cc=new CircleClass();
cc.display();
}
}
结QAdapter模式是一个很常用的模式,它将一个(或多个)cȝ接口转换成我们需要类所具备的一个接口。它的实现方式是Q创Z个具备所需接口的类Q然后包装原有类的方法,q样实际上就包含了被适配的对象。它主要适用于以下几U情况:(x)
1Q?nbsp;你希望用他人编写的子程序或Ҏ(gu)Q因Z需要它所执行的功能?/span>
2Q?nbsp;你无法将q个子程序直接加入程序中?/span>
3Q?nbsp;子程序的接口或调用方式与需要用它的相兛_象不完全相同?/span>
为子pȝ中的一l接口提供一个统一接口?/span>Facade模式定义了一个更高层的接口,使子pȝ更加Ҏ(gu)使用?/span>
大致意思是_(d)(x)使用一U比原有方式更简单的办法与系l交互。例如,我们把一个很文g的文Ӟ攑֜了第二抽屉里Q而第二个抽屉的钥匙放在了W一个抽屉里Q我们要惛_个文ӞW一步肯定要拿到W一个抽屉的钥匙Q然后打开它再拿出W二个抽屉的钥匙Q最后打开W二个抽屉取出文件?/span>
我就上面说的那个情Ş写一下实C码,首先我们要实C个子pȝ,呵呵Q把抽屉比喻成系l,有点夸张了(DrawerOne?/span>DrawerTwoQ:(x)
class DrawerOne {
public void open(){
System.out.println("W一个抽屉被打开?/span>");
getKey();
}
public void getKey(){
System.out.println("得到W二个抽屉的钥匙");
}
}
class DrawerTwo{
public void open(){
System.out.println("W二个抽屉被打开?/span>");
getFile();
}
public void getFile(){
System.out.println("得到q个重要文g");
}
}
public class Client{
public static void main(String []args){
DrawerOne darwerOne=new DrawerOne();
DrawerTwo darwerTwo=new DrawerTwo();
darwerOne.open();
darwerTwo.open();
}
}
׃没有使用Façade模式Q可以看到要惛_到这个文件要首先打开W一个抽屉,然后再打开W二个抽屉,在我们实际所开发的pȝ中,有时候客戯实现某一操作Qƈ不需要知道实现这一操作的详l步骤,而是单地点击某一个按钮就可以得到自己惌的结果。下面对上面的代码?/span>Façade模式q行改进Q徏立一?/span>FacadeDrawerc:(x)
class DrawerFacade{
DrawerOne darwerOne=new DrawerOne();
DrawerTwo darwerTwo=new DrawerTwo();
public void open(){
darwerOne.open();
darwerTwo.open();
}
}
修改Clientc:(x)
public class DrawerClient{
public static void main(String []args){
DrawerFacade drawer=new DrawerFacade();
drawer.open();
}
}
输出l果如下Q?/span>
W一个抽屉被打开?/span>
得到W二个抽屉的钥匙
W二个抽屉被打开?/span>
得到q个重要文g
正如上面所_(d)客户?/span>clientQ它q不需要关心子pȝQ而是兛_DrawerFacade所留下来的和外部交互的接口Q而子pȝ?/span>DrawerFacade的聚合?/span>
以上只是个h拙见Q哪里有不正的地方Q希望大家多多批评指正?/span>^_^
Facade模式主要适用于以下几U情?/span>:
1) 不需要用一个复杂系l的所有功能,而且可以创徏一个新的类Q包含访问系l的所有规则。如果只需要用系l的部分功能Q那么你为新cL创徏?/span>API比原系l的API单的多?/span>
2) 希望装或者隐藏系l原pȝ?/span>
3) 希望使用原系l的功能Q而且q希望增加一些新的功能?/span>
4) ~写新类的成本小于所有h学会(x)使用或者未来维护原pȝ上所需的成本?/span>