文章大纲
一、策略模式
二、观察者模式
三、工厂模式
四、单例模式
五、其他模式
六、设计模式总结
七、参考文章
一、策略模式
现在假设我们有个“鸭子项目”,首先我们用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