VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • java教程之Java常见设计模式学习(非原创)

文章大纲

一、策略模式
二、观察者模式
三、工厂模式
四、单例模式
五、其他模式
六、设计模式总结
七、参考文章

 

一、策略模式

现在假设我们有个“鸭子项目”,首先我们用OOP(面向对象)的角度设计这个项目,找到鸭子中共同的特性抽取在父类中并具体实现,不同的特性不实现,由子类具体实现,好下面看代码:

public abstract class Duck {
    /**
     * 叫声和游泳为相同的特性抽取并具体实现
     */
    public void Quack() {
        System.out.println("~~gaga~~");
    }
    public void swim() {
        System.out.println("~~im swim~~");
    }

    /**
     * 外貌为不同的特性设计为抽象的方法,有子类具体实现
     */
    public abstract void display();

}

现在我们看它的子类:

public class GreenHeadDuck extends Duck {
    @Override
    public void display() {
        System.out.println("**GreenHead**");
    }
}
public class RedHeadDuck extends Duck {
    @Override
    public void display() {
        System.out.println("**RedHead**");
    }
}

好的,现在我们可以看到使用OOP可以很好的解决目前的问题,但是我们往往是需求不断,所以我们现在又来一个新需求:添加会飞的鸭子
好办啊,我们只要在父类中添加一个新的方法:

public abstract class Duck {
    /**
     * 叫声和游泳为相同的特性抽取并具体实现
     */
    public void Quack() {
        System.out.println("~~gaga~~");
    }
    public void swim() {
        System.out.println("~~im swim~~");
    }

    /**针对新需求的方法*/
    public void Fly() {
        System.out.println("~~im fly~~");
    }

    /**
     * 外貌为不同的特性设计为抽象的方法,有子类具体实现
     */
    public abstract void display();

}

问题来了,这个Fly让所有子类都会飞了,这是不科学的。
继承的问题:对类的局部改动,尤其超类的局部改动,会影响其他部分。影响会有溢出效应
好现在我们继续用OOP的方式去解决,使其子类覆盖Fly:

public class GreenHeadDuck extends Duck {
    @Override
    public void display() {
        System.out.println("**GreenHead**");
    }

    /**
     * 覆盖
     * */
    public void Fly() {
        System.out.println("~~no fly~~");
    }
}

可以看到貌似问题是解决了,我们现在的鸭子类只有2种,如果有上百种呢,那不是都要去覆盖。所以这不是一种好的设计模式

分析问题:
需要新的设计方式,应对项目的扩展性,降低复杂度:
1)分析项目变化与不变部分,提取变化部分,抽象成接口+实现;
2)鸭子哪些功能是会根据新需求变化的?叫声、飞行…
我们将变化的功能设计成接口,下面看代码:

public interface FlyBehavior {
    void fly();
}
public interface QuackBehavior {
    void quack();
}

来看看新的Duck类:

public abstract class Duck {
    /**
     * 父类定义行为出来,但是没有具体实例化
     */
    FlyBehavior mFlyBehavior;
    QuackBehavior mQuackBehavior;

    public Duck() {
    }

    public void Fly() {
        if (mFlyBehavior!=null) {
            mFlyBehavior.fly();
        }
    }

    public void Quack() {
        if (mQuackBehavior!=null) {
            mQuackBehavior.quack();
        }
    }

    /**
     * 子类可以透过两个行为的set方法去动态改变自己的具体行为
     */
    public void setmFlyBehavior(FlyBehavior mFlyBehavior) {
        this.mFlyBehavior = mFlyBehavior;
    }

    public void setmQuackBehavior(QuackBehavior mQuackBehavior) {
        this.mQuackBehavior = mQuackBehavior;
    }

    public abstract void display();
}

然后在去看看子类:

public class RedHeadDuck extends Duck{

    public RedHeadDuck() {
        mFlyBehavior=new GoodFlyBehavior();
        mQuackBehavior=new GaGaQuackBehavior();
    }
    @Override
    public void display() {
        System.out.println("redDuck");
    }
}
public class GreenHeadDuck extends Duck{

    public GreenHeadDuck() {
        mFlyBehavior=new BadFlyBehavior();
        mQuackBehavior=new GeGeQuackBehavior();
    }
    @Override
    public void display() {
        System.out.println("greenDuck");
    }

}

再来看看接口实现类:

public class BadFlyBehavior implements FlyBehavior{

    @Override
    public void fly() {
        System.out.println("bad fly");
    }

}
public class GoodFlyBehavior implements FlyBehavior{

    @Override
    public void fly() {
        System.out.println("good fly");
    }

}
public class NoFlyBehavior implements FlyBehavior{

    @Override
    public void fly() {
        System.out.println("No fly");
    }

}
public class GaGaQuackBehavior implements QuackBehavior{

    @Override
    public void quack() {
        System.out.println("gaga quack");
    }

}
public class GeGeQuackBehavior implements QuackBehavior{

    @Override
    public void quack() {
        System.out.println("gege quack");
    }

}
public class NoQuackBehavior implements QuackBehavior{

    @Override
    public void quack() {
        System.out.println("No Quack");
    }

}

好的,现在我们来分析一下这个设计,在父类中我们定义好FlyBehavior & QuackBehavior 两个行为接口,然后在子类构造方法中分别设定对应的具体行为
现在来测试一下:

 
 

策略模式:分别封装行为接口,实现算法族,超类里放行为接口对象,在子类里具体设定行为对象。原则就是:分离变化部分,封装接口,基于接口编程各种功能。此模式让行为算法的变化独立于算法的使用者

二、观察者模式

现在假设我们有一个需要为A公司实时提供天气的天气预报接口项目,好的,首先我们还是以OOP的方式去解决问题,首先我们创建一个天气台对象并提供相关方法假设它可以实时为A公司提供天气数据,下面看代码:

public class MeteorologicalStation {
    private float pressure;
    private float temperature;
    private float humidity;
    private ACompany company;

    public MeteorologicalStation(ACompany company) {
        this.company=company;
    }

    public float getPressure() {
        return pressure;
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    /**
     * 实时提供天气情况
     * */
    public void uploadData(float pressure,float temperature,float humidity){
        company.getMeteorologicalStationData(pressure, temperature, humidity);
    }

}

ACompany为A公司:

public class ACompany {
    public void getMeteorologicalStationData(float pressure, float temperature, float humidity) {
        System.out.println("pressure: "+pressure+",temperature: "+temperature+",humidity: "+humidity);
    }
}

测试

 
 

好的,到了这里我们从OOP角度已经初步解决了这个项目,假设现在B公司也需要实时获取天气台提供的天气情况,如果我们还是继续使用OOP去设计这个项目,需要在天气台接口中添加BCompany,并在实时更新的函数中调用BCompany的获取天气的函数,这貌似可以解决这个需求,但是加入后续加入C,D,E..公司,那么天气台接口修改的代码也是比较大,但是我们知道在通常实际开发中,接口一般不会随着他人的接入而更改,所以现在我们使用观察者模式去设计这个项目:

/**
 * 该接口相当于天气台管理者,谁想接入我和离开我都必须通过它去管理
 * */
public interface Subject {
    void registerObserver(Observer o);
    void removeObserver(Observer o);
    void notifObserver();
}
/**
 * 通过该接口,每个想要接入的公司实现该方法即可。
 */
public interface Observer {
    void getMeteorologicalStationData(float pressure,float temperature,float humidity);
}
public class MeteorologicalStation implements Subject {
    private float pressure;
    private float temperature;
    private float humidity;
    private ArrayList<Observer> observers;

    public MeteorologicalStation(ACompany company) {
        observers = new ArrayList<Observer>();
    }

    public float getPressure() {
        return pressure;
    }

    public float getTemperature() {
        return temperature;
    }

    public float getHumidity() {
        return humidity;
    }

    public void uploadData(float pressure, float temperature, float humidity) {
        this.pressure = pressure;
        this.temperature = temperature;
        this.humidity = humidity;
         notifObserver();
    }

    @Override
    public void registerObserver(Observer o) {
        if (!observers.contains(o)) {
            observers.add(o);
        }
    }

    @Override
    public void removeObserver(Observer o) {
        if (observers.contains(o)) {
            observers.remove(o);
        }
    }

    @Override
    public void