Java常用设计模式简易代码Demo:单例、工厂、代理、模板、观察者、适配器、策略、装饰者

一、单例模式

节省内存。

public class SingleMode {
    private static volatile SingleMode singleMode = null;//懒汉式
    private SingleMode() {
    }
    public static SingleMode getInstance() {
        if (singleMode == null) {
            synchronized (SingleMode.class) {
                if (singleMode == null) {
                    singleMode = new SingleMode();
                }
            }
        }
        return singleMode;
    }
}

二、工厂模式

将创建实例的工作与使用实例的工作分开,用户不再关心对象是如何创建的,只需要知道工厂api就可以得到对象了。

2.1简单工厂:

interface Sender{
    void send();
}
class MailSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送邮件信息!");
    }
}
class SmsSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送短信消息!");
    }
}
class SenderFactory {
    public static Sender newMailSender(){
        return new MailSender();
    }
    public static Sender newSmsSender(){
        return new SmsSender();
    }
}
class FactoryMode{
    public static void main(String[] args) {
        Sender sender = SenderFactory.newMailSender();
        Sender sender1 = SenderFactory.newSmsSender();
        sender.send();
        sender1.send();
    }
}

SenderFactory维护麻烦,不优雅,工厂方法模式优化。

2.2工厂方法模式:

interface Sender{
    void send();
}
class MailSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送邮件信息!");
    }
}
class SmsSender implements Sender{
    @Override
    public void send() {
        System.out.println("发送短信消息!");
    }
}
interface Factory{
    Sender createSender();
}
class MailSenderFactory implements Factory{
    @Override
    public Sender createSender() {
        return new MailSender();
    }
}
class SmsSenderFactory implements Factory{
    @Override
    public Sender createSender() {
        return new SmsSender();
    }
}
class FactoryMethodMode{
    public static void main(String[] args) {
        Sender sender = new MailSenderFactory().createSender();
        Sender sender1 = new SmsSenderFactory().createSender();
        sender.send();
        sender1.send();
    }
}

但是,如果想把Sender分类处理(4G对应一个Sender,5G对应一个Sender)或者实际情况中必须要分类处理呢?抽象工厂模式(工厂方法模式属于抽象工厂,是抽象工厂的一种特例)。

2.3抽象工厂模式:

interface SenderA {
    void send();//4G发送
}
interface SenderB {
    void send();//5G发送
}
class MailSender implements SenderA {
    @Override
    public void send() {
        System.out.println("4G发送邮件信息!");
    }
}
class SmsSender implements SenderA {
    @Override
    public void send() {
        System.out.println("4G发送短信消息!");
    }
}
class NewMailSender implements SenderB {
    @Override
    public void send() {
        System.out.println("5G发送邮件消息!");
    }
}
class NewSmsSender implements SenderB {
    @Override
    public void send() {
        System.out.println("5G发送短信消息!");
    }
}
interface Factory {
    SenderA createSenderA();
    SenderB createSenderB();
}
class MailSenderFactory implements Factory {
    @Override
    public SenderA createSenderA() {
        return new MailSender();
    }
    @Override
    public SenderB createSenderB() {
        return new NewMailSender();
    }
}
class SmsSenderFactory implements Factory {
    @Override
    public SenderA createSenderA() {
        return new SmsSender();
    }
    @Override
    public SenderB createSenderB() {
        return new NewSmsSender();
    }
}
class AbstractFactoryMode {
    public static void main(String[] args) {
        MailSenderFactory mailSenderFactory = new MailSenderFactory();
        SmsSenderFactory smsSenderFactory = new SmsSenderFactory();
        mailSenderFactory.createSenderA().send();
        mailSenderFactory.createSenderB().send();
        smsSenderFactory.createSenderA().send();
        smsSenderFactory.createSenderB().send();
    }
}

三、代理模式

通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,扩展目标对象的功能。

遵循编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需修改,可以通过代理的方式来扩展该方法。

3.1静态代理:

interface UserDao{
    void save();
}
class UserDaoImpl implements UserDao{
    @Override
    public void save() {
        System.out.println("保存了数据...");
    }
}
class UserDaoImplProxy implements UserDao{
    UserDao userDao;
    public UserDaoImplProxy(UserDao userDao) {
        this.userDao = userDao;
    }
    @Override
    public void save() {
        System.out.println("--开启事务");
        userDao.save();
        System.out.println("--关闭事务");
    }
}
class StaticProxyModeMain{//静态代理模式
    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        UserDaoImplProxy userDaoImplProxy = new UserDaoImplProxy(userDao);
        userDaoImplProxy.save();
    }
}

因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护.动态代理优化。

3.2JDK动态代理:

代理对象是利用JDK的API,动态的在内存中创建代理对象.

class JdkProxyFactory{
    public static Object getInstance(Object target){
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            //代理对象调用触发invoke()
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("--开启事务");
                Object invoke = method.invoke(target, args);//去调用目标对象方法
                System.out.println("--提交事务");
                return invoke;//方法返回值
            }
        });
        return proxy;//返回代理对象
    }
}
class JdkProxyModeMain{
    public static void main(String[] args) {
        UserDaoImpl userDao = new UserDaoImpl();
        //动态的在内存中创建代理对象,代理对象和UserDaoImpl一样实现了UserDao接口,即是UserDao接口的实现类
        UserDao proxy = (UserDao) JdkProxyFactory.getInstance(userDao);
        proxy.save();
    }
}

目标对象一定要实现接口,否则不能用JDK动态代理。

3.3cglib子类代理:

在内存中构建一个子类对象从而实现对目标对象功能的扩展.Cglib包的底层是通过使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类.

引入cglib的jar文件,但是Spring的核心包中已经包括了Cglib功能,所以直接引入spring-core-xx.jar即可;

class AdminDao{
    public void save(){
        System.out.println("保存了数据...");
    };
}
class CglibProxyFactory implements MethodInterceptor {
    Object target;
    public CglibProxyFactory(Object target) {
        this.target = target;
    }
    //获取代理对象
    public Object getInstance(){
        Enhancer enhancer = new Enhancer();//1.工具类
        enhancer.setSuperclass(target.getClass());//2.设置父类
        enhancer.setCallback(this);//3.设置回调函数。将当前的工厂对象作为回调对象
        Object obj = enhancer.create();//4.创建子类(代理对象)
        return obj;
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("--开启事务");
        Object returnValue = method.invoke(target, objects);//去调用目标对象方法
        System.out.println("--提交事务");
        return returnValue;
    }
}
class CglibProxyModeMain{
    public static void main(String[] args) {
        AdminDao adminDao = new AdminDao();
        AdminDao proxy = (AdminDao) new CglibProxyFactory(adminDao).getInstance();
        proxy.save();
    }
}

在Spring的AOP编程中:

如果加入容器的目标对象有实现接口,用的JDK代理

如果目标对象没有实现接口,用的Cglib代理

四、模板模式

模板模式主要由抽象模板(Abstract Template)角色和具体模板(Concrete Template)角色组成。

//抽象模板
abstract class OneDay{
    public void getup(){
        System.out.println("起床");
    }
    public void sleep(){
        System.out.println("睡觉了...");
    }
    //具体模板执行流程
    public void dayAll(){
        getup();
        goWork();
        goHome();
        sleep();
    }
    public abstract void goWork();
    public abstract void goHome();
}
class Worker extends OneDay{
    @Override
    public void goWork() {
        System.out.println("骑着小毛驴去上班");
    }
    @Override
    public void goHome() {
        System.out.println("骑着小毛驴回家");
    }
}
class Boss extends OneDay{
    @Override
    public void goWork() {
        System.out.println("开着大奔上班去");
    }
    @Override
    public void goHome() {
        System.out.println("开着大奔回家");
    }
}
class TemplateMethodModeMain{
    public static void main(String[] args) {
        new Boss().dayAll();
        new Worker().dayAll();
    }
}

优点:模板方法所不变的行为搬到超类,去除子类中的重复代码,提供了一个很好了代码复用平台;子类不用关心具体执行流程和公共行为,只需实现要求你实现的方法即可。

缺点:当类的功能越来越多,变得复杂时,抽象类的管理和扩展就变得复杂了。

五、观察者模式

当被观察者状态发生改变时,需要通知相应的观察者,使这些观察者对象能够自动更新。

//被观察者通用接口
interface Observable {
    void addObserver(Observer observer);//添加观察者
    void removeObServer(Observer observer);//移除观察者
    void notifyAllObserver();//通知所有观察者
}
class Weather implements Observable {
    private List list = new ArrayList<>();
    private double temperature;
    public void setTemperature(double temperature) {
        this.temperature = temperature;
    }
    @Override
    public void addObserver(Observer observer) {
        list.add(observer);
    }
    @Override
    public void removeObServer(Observer observer) {
        list.remove(observer);
    }
    @Override
    public void notifyAllObserver() {
        for (Observer observer : list) {
            observer.update(temperature);
        }
    }
}
//观察者通用接口
interface Observer {
    void update(double temperature);
}
class Person implements Observer{
    @Override
    public void update(double temperature) {
        System.out.println("温度更新了,当前温度值:"+temperature+",快回家收衣服啊...");
    }
}
class Dog implements Observer{
    @Override
    public void update(double temperature) {
        System.out.println("温度更新了,当前温度值:"+temperature+",天气好热,找个大树乘凉去...");
    }
}
class ObserverModeMain{
    public static void main(String[] args) {
        Weather weather = new Weather();
        weather.addObserver(new Person());
        weather.addObserver(new Dog());
        weather.setTemperature(38D);
        weather.notifyAllObserver();
    }
}

六、适配器模式

Target(目标抽象类DC5Adapter):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。

Adapter(适配器类ChinaDC5Adapter):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。

Adaptee(适配者类AC220):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。

class AC220{
    private final int output = 220;
    public int outputAC(){
        return output;
    }
}
//适配通用接口
interface DC5Adapter{
    int outputDC5();
}
//中国的手机适配器
class ChinaDC5Adapter implements DC5Adapter{
    private AC220 ac = new AC220();
    @Override
    public int outputDC5() {
        int i = ac.outputAC();
        System.out.println("适配前,电压:"+i);
        int dc = i / 44;
        System.out.println("适配后,电压为:"+dc);
        return dc;
    }
}
class AdapterModeMain{
    public static void main(String[] args) {
        //适配器对象
        DC5Adapter dc5Adapter = new ChinaDC5Adapter();
        int i = dc5Adapter.outputDC5();
    }
}

七、策略模式

环境类(Context):用来操作策略的上下文环境。

抽象策略类(Strategy):策略的抽象

具体策略类(ConcreteStrategy):具体的策略实现,每一种出行方式的具体实现。

//策略通用接口
interface Operation{
    void execute(int i, int j);
}
//策略实现类
class Add implements Operation{
    @Override
    public void execute(int i, int j) {
        int result = i+j;
        System.out.println("加法结果:"+result);
    }
}
class Sub implements Operation{
    @Override
    public void execute(int i, int j) {
        int result = i -j;
        System.out.println("减法结果:"+result);
    }
}
//上下文环境类
class Context{
    Operation operation;
    public Context(Operation operation) {
        this.operation = operation;
    }
    public void executeStrategy(int i, int j){
        operation.execute(i, j);//调用的是实现类的具体实现
    }
}
class StrategyModeMain{
    public static void main(String[] args) {
        int i=10,j=20;
        new Context(new Add()).executeStrategy(i,j);
        new Context(new Sub()).executeStrategy(i,j);
    }
}

优点:策略实现类可灵活实现。缺点:策略实现类繁多且需要开发者全部了解,维护麻烦。

八、装饰者模式

扩展对象的功能,是继承关系的一个替代。装饰模式可以在不创造更多子类的情况下,将对象的功能加以扩展。即扩展对象功能但不使用继承。

interface Animal{
    void function();
}
class Cat implements Animal{
    @Override
    public void function() {
        System.out.println("我会吃饭睡觉...");
    }
}
class Decorator implements Animal{
    Animal animal;//组合模式
    public Decorator(Animal animal) {
        this.animal = animal;
    }
    @Override
    public void function() {
        animal.function();//实际调用的是实现类方法
    }
}
class CatDecorator extends Decorator{
    public CatDecorator(Animal animal) {
        super(animal);
    }
    @Override
    public void function() {
        super.function();
        System.out.println("我还会抓老鼠...");
    }
}
class DecoratorModeMain{
    public static void main(String[] args) {
        Cat cat = new Cat();
        System.out.println("装饰前:");
        cat.function();
        CatDecorator catDecorator = new CatDecorator(cat);
        System.out.println("装饰后:");
        catDecorator.function();
    }
}

 

你可能感兴趣的:(JAVA,设计模式)