Java设计模式

Java常见设计模式

2019-02-19  本文已影响3人  zhangweiheb

1.设计模式六大原则

2. 设计模式分类

GoF 提出的设计模式总共有 23 种,根据目的准则分类,分为三大类。

另外,随着发展也涌现出很多新的设计模式:规格模式、对象池模式、雇工模式、黑板模式和空对象模式等。

2.1创建型设计模式

2.1.1 单例模式

单例模式的 7 种写法:

https://www.jianshu.com/p/e17f82e8ebc9

7种单例设计模式的设计.png

2.1.2 工厂方法模式

定义:
定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。
结构图:

工厂方法模式结构图
角色:

例:
(1)创建抽象工厂

public abstract class ComputerFactory {
    public abstract <T extends Computer> T createComputer(Class<T> clz);
}

(2)具体工厂

public class GDComputerFactory extends ComputerFactory {
    @Override
    public <T extends Computer> T createComputer(Class<T> clz) {
        Computer computer;
        String className = clz.getName();
        try {
            computer = Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return (T) computer;
    }
}

2.1.3 创造者模式(生成器模式)

定义:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
结构图:

创造者模式结构图
角色:

使用场景

优点

缺点

2.2 结构型设计模式

结构型设计模式是从程序的结构上解决模块之间的耦合问题。

2.2.1 代理模式

定义:
为其他对象提供一种代理以控制对这个对象的访问。
结构图:

代理模式结构图
角色:
静态代理

(1)抽象主题类

public interface IShopping {
    void buy();
}

(2)真实主题类

public class Xiaoming implements IShopping {
    @Override
    public void buy() {
        System.out.println("小明买东西");
    }
}

(3)代理类

public class Purchasing implements IShopping {
    private IShopping mShopping;
    public Purchasing(IShopping shopping) {
        mShopping = shopping;
    }
    @Override
    public void buy() {
        mShopping.buy();
    }
}

(4)客户端类

public class Client {
    public static void main(String[] args) {
        IShopping xiaoming = new Xiaoming();
        IShopping purchasing = new Purchasing(xiaoming);
        purchasing.buy();
    }
}
动态代理

在代码运行时通过反射来动态地生成代理类对象,并确定到底来代理谁。

public class DynamicPurchasing implements InvocationHandler {
    private Object obj;
    public DynamicPurchasing(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(obj, args);
        if("buy".equals(method.getName())) {
            System.out.println("买东西");
        }
        return result;
    }
}
public class Client {
    public static void main(String[] args) {
        IShopping xiaoming = new Xiaoming();
        DynamicPurchasing dynamicPurchasing = new DynamicPurchasing(xiaoming);
        IShopping purchasing = (IShopping) Proxy.newProxyInstance(xiaoming.getClass.getClassLoader(),
            new Class[]{IShopping.class}, dynamicPurchasing);
        purchasing.buy();
    }
}

代理模式的类型
代理模式从编码的角度来说可以分为静态代理和动态代理,而从使用范围来讲则可分为以下 4 种类型:

优点

2.2.2 装饰模式

定义
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
结构图

装饰模式结构图
角色

实现
杨过本身就会全真剑法,又有两位前辈洪七公和欧阳锋向杨过传授打狗棒法和蛤蟆功,这样杨过除了会全真剑法,还会打狗棒法和蛤蟆功。洪七公和欧阳锋就起到了“装饰”杨过的作用。
(1)抽象组件

public abstract class Swordman {
    public abstract void attackMagic();
}

(2)组件具体实现类

public class YangGuo extends Swordman {
    @Override
    public void attackMagic() {
        System.out.println("杨过使用全真剑法");
    }
}

(3)抽象装饰者

public abstract class Master extends Swordman {
    private Swordman mSwordman;
    public Master(Swordman swordman) {
        this.mSwordman = swordman;
    }
    @Override
    public void attackMagic() {
        mSwordman.attackMagic();
    }
}

(4)装饰者具体实现类

public class HongQigong extends Master {
    public HongQigong(Swordman swordman) {
        super(swordman);
    }
    public void teachAttackMagin() {
        System.out.println("洪七公教授打狗棒法");
        System.out.println("杨过使用打狗棒法");
    }
    @Override
    public void attackMagic() {
        super.attackMagic();
        teachAttackMagin();
    }
}

public class OuYangFeng extends Master {
    public OuYangFeng(Swordman swordman) {
        super(swordman);
    }
    public void teachAttackMagin() {
        System.out.println("欧阳锋教授蛤蟆功");
        System.out.println("杨过使用蛤蟆功");
    }
    @Override
    public void attackMagic() {
        super.attackMagic();
        teachAttackMagin();
    }
}

(5)客户端调用

public class Client {
    public static void main(String[] args) {
        YangGuo yangguo = new YangGuo();
        HongQigong hongqigong = new HongQigong(yangguo);
        hongqigong.attackMagic();
        OuYangFeng ouyangfeng = new OuYangFeng(yangguo);
        ouyangfeng.attackMagic();
    }
}

使用场景

优点

缺点

2.2.3 外观模式(门面模式)

定义
要求一个子系统的外部与内部的通信必须通过一个统一的对象进行。此模式提供一个高层的接口,使得子系统更易于使用。
结构图

外观模式结构图
角色
/**
 * 子系统招式
 */
public class ZhaoShi {
    public void TaiJiQuan() {
        System.out.println("使用招式太极拳");
    }
    public void QiShangQuan() {
        System.out.println("使用招式七伤拳");
    }
    public void ShengHuo() {
        System.out.println("使用招式圣火令");
    }
}

/**
 * 子系统内功
 */
public class NeiGong {
    public void JiuYang() {
        System.out.println("使用九阳神功");
    }
    public void QianKun() {
        System.out.println("使用乾坤大挪移");
    }
}

/**
 * 子系统经脉
 */
public class JingMai {
    public void jingmai() {
        System.out.println("开启经脉");
    }
}

(2)外观类

/**
 * 外观类张无忌
 */
public class ZhangWuJi {
    private JingMai jingmai;
    private ZhaoShi zhaoshi;
    private NeiGong neigong;
    public ZhangWuJi() {
        jingmai = new JingMai();
        zhaoshi = new ZhaoShi();
        neigong = new NeiGong();
    }
    public void QianKun() {
        jingmai.jingmai();
        neigong.QianKun();
    }
    public void QiShang() {
        jingmai.jingmai();
        neigong.JiuYang();
        zhaoshi.QiShangQuan();
    }
}

(3)客户端调用

public class Client {
    public static void main(String[] args) {
        ZhangWuJi zhangwuji = new ZhangWuJi();
        zhangwuji.QianKun();
        zhangwuji.QiShang();
    }
}

使用场景

优点

缺点

2.2.4 享元模式

定义
使用共享对象有效地支持大量细粒度的对象。
结构图

享元模式结构图
角色

实现
“双11“促销中的商品信息。
(1)抽象享元角色

public interface IGoods {
    public void showGoodsPrice(String name);
}

(2)具体享元角色

public class Goods implements IGoods {
    private String name;
    private String version;
    public Goods(String name) {
        this.name = name;
    }
    @Override
    public void showGoodsPrice(String version) {
        if("32G".equals(version)) {
            System.out.println("价格为5199元");
        } else if("128G".equals(version)) {
            System.out.println("价格为5999元");
        }
    }
}

(3)享元工厂

public class GoodsFactory {
    private static Map<String, Goods> pool = new HashMap<String, Goods>();
    public static Goods getGoods(String name) {
        if(pool.containsKey(name)) {
            System.out.println("使用缓存,key 为:" + name);
            return pool.get(name);
        } else {
            Goods goods = new Goods(name);
            pool.put(name, goods);
            System.out.println("创建商品,key 为:" + name);
            return goods;
        }
    }
}

(4)客户端调用

public class Client {
    public static void main(String[] args) {
        Goods goods1 = GoodsFactory.getGoods("iPhone7");
        goods.showGoodsPrice("32G");
        Goods goods2 = GoodsFactory.getGoods("iPhone7");
        goods.showGoodsPrice("128G");
    }
}

使用场景

优点

2.3 行为型设计模式

行为性模式主要处理类或对象如何交互以及如何分配职责。

2.3.1 策略模式

定义
定义一系列的算法,把每一个算法封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而独立变化。
结构图

策略模式结构图
角色

实现

/**
 * 战斗策略
 */
public interface FightingStrategy {
    public void fighting();
}

(2)具体策略实现

public class WeakRivalStrategy implements FightingStrategy {
    @Override
    public void fighting() {
        System.out.println("遇到了较弱的对手,张无忌使用太极剑");
    }
}

public class CommonRivalStrategy implements FightingStrategy {
    @Override
    public void fighting() {
        System.out.println("遇到了普通的对手,张无忌使用圣火令神功");
    }
}


public class StrongRivalStrategy implements FightingStrategy {
    @Override
    public void fighting() {
        System.out.println("遇到了强大的对手,张无忌使用乾坤大挪移");
    }
}

(3)上下文角色

public class Context {
    private FightingStrategy fightingStrategy;
    public Context(FightingStrategy fightingStrategy) {
        this.fightingStrategy = fightingStrategy;
    }
    public void fighting() {
        fightingStrategy.fighting();
    }
}

(4)客户端调用

public class ZhangWuJi {
    public static void main(String[] args) {
        Context context = new Context(new WeakRivalStrategy());
        context.fighting();
    }
}

使用场景

优点

缺点

2.3.2 模板方法模式

定义
定义一个操作中的算法框架,而将一些步骤延迟到子类中,使得子类不改变一个算法的结构即可定义算法的某些特定步骤。
结构图

模板方法模式结构图
角色

实现
(1)创建抽象类,定义算法框架

public abstract class AbstractSwordman {
    public final void fighting() {
        neigong();
        meridian();
        if(hasWeapons()) {
            weapons();
        }
        moves();
        hook();
    }
    protected void hook() {};
    protected abstract void neigong();
    protected abstract void weapons();
    protected abstract void moves();
    protected void merdian() {
        System.out.println("开启正经与奇经");
    }
    protected boolean hasWeapons() {
        return true;
    }
}

(2)具体实现类

public class ZhangWuJi extends AbstractSwordman {
    @Override
    protected void neigong() {
        System.out.println("运行九阳神功");
    }
    @Override
    protected void weapons() {}
    @Override
    protected void moves() {
        System.out.println("使用乾坤大挪移");
    }
    @Override
    protected boolean hasWeapons() {
        return false;
    }
}

(3)客户端调用

public class Client {
    public static void main(String[] args) {
        ZhangWuJi zhangwuji = new ZhangWuJi();
        zhangwuji.fighting();
    }
}

使用场景

优点

缺点

2.3.3 观察者模式(发布-订阅模式)

定义
定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
结构图

观察者模式结构图
角色

实现
微信某个公众号的更新通知。
(1)抽象观察者

public interface Observer {
    public void update(String message);
}

(2)具体观察者

public class WeixinUser implements Observer {
    private String name;
    public WeixinUser(String name) {
        this.name = name;
    }
    @Override
     public void update(String message) {
        System.out.println(name + "-" + message);
     }
}

(3)抽象被观察者

public interface Subject {
    public void attach(Observer observer);
    public void detach(Observer observer);
    public void notify(String message);
}

(4)具体被观察者

public class SubscriptionSubject implements Subject {
    private List<Observer> weixinUserList = new ArrayList<Observer>();
    @Override
    public void attach(Observer observer) {
        weixinUserList.add(observer);
    }
    @Override
    public void detach(Observer observer) {
        weixinUserList.remove(observer);
    }
    @Override
    public void notify(String message) {
        for(Observer observer : weixinUserList) {
            observer.update(message);
        }
    }
}

(5)客户端调用

public class Client {
    public static void main(String[] args) {
        SubscriptionSubject subject = new SubscriptionSubject();
        WeixinUser user1 = new WeixinUser("xiaoming");
        WeixinUser user2 = new WeixinUser("xiaohua");
        subject.attach(user1);
        subject.attach(user2);
        subject.notify("专栏更新");
    }
}

使用场景

优点

缺点

上一篇下一篇

猜你喜欢

热点阅读