JAVA架构师半小时学会常用设计模式

以下为个人学习后的感悟,若有问题请大神们指出来~

目录

一、Proxy Pattern 代理模式(需要代理人)

二、Singleton Pattern 单例模式(不需要多次实例化某对象,节省资源消耗)

三、Strategy Pattern 策略模式(商场有多种优惠策略)

四、Template Pattern 模版模式(全国统考,保持试卷一致,修改变更)

五、Abstract Factory Pattern 抽象工厂模式(服务端连接不同数据库),含反射用法示例

一、Proxy Pattern 代理模式(需要代理人)
    概念:代理是代替另一个类(这里我称呼它为“被代理类”),它通常和代理的类拥有一样的接口,并且实现接口。

    个人理解:现在每天都会诞生无数的明星,如果你是某小公司的负责人,需要邀请明星来拍摄广告或者邀请做形象代言人,一般是没办法和明星直接面谈,那怎么办呢?明星的经纪人就出现了,有生意找经纪人谈,如果有什么问题可以委托经纪人和明星内部沟通交流。

      代码示例:

步骤一,定义共同的接口SubjectApi抽象类

abstract class SubjectApi {
    public abstract void Request();
}


步骤二,代理者Proxy类和被代理者RealSubject类都继承抽象类SubjectApi,并实现接口

//被代理者类

public class RealSubject extends SubjectApi {
    @Override
    public void Request() {
        System.out.println("真实的请求");
    }
}


//代理者类

public class Proxy extends SubjectApi {
    private RealSubject realSubject;         ----注意,这里用了关联的方式
    @Override
    public void Request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.Request();
    }
}


//访问者

public class DemoTest {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();
        proxy.Request();
    }
}


输出结果:

真实的请求

二、Singleton Pattern 单例模式(不需要多次实例化某对象,节省资源消耗)
       概念:单例模式,常用于封装之后,可以在生命周期范围内维持使用它。只需要创建一次,相当于懒实例化的效果。比如在构造函数中需要执行比如访问远程数据库的操作,操作可能会很耗时和耗资源。

     个人理解:比如在一定长的时间范围内,需要频繁调用某服务的接口,这时如果该服务只实例化一次,在频繁调用的时候就不需要每次都实例化一遍。

代码示例一(双重锁定示例):

步骤一,创建单例对象,对外仅提供访问实例化的对象方法GetInstance。判断是否已实例化,如果没有则new操作创建并实例化对象 ;已实例化则直接返回对象。

public class Singleton {
    private static Singleton instance;
    private static final Object syncRoot = new Object();

    private Singleton() {

    }

    public static Singleton GetInstance() {
        if (instance == null) {                        ----双重锁定,当对象已实例化时,其他线程访问时就不会再做加锁操作
            synchronized(Singleton.class){             ----当多线程访问时,加锁保证对象不会被实例化多次
                if (instance == null) {
                    instance = new Singleton();
                    System.out.println("实例化对象");
                }
            }
        }
        return instance;
    }
}


步骤二,访问者访问对象

public class Test {
    public static void main(String[] args) {
        Singleton s1 = Singleton.GetInstance();
        Singleton s2 = Singleton.GetInstance();
        if (s1 == s2) {
            System.out.println("两个对象是相同的实例");
        }
    }
}


代码示例二(饿汉式(静态常量)静态初始化示例):

public class SingletonInit {
    private static SingletonInit instance = new SingletonInit();
    private SingletonInit() {
    }

    public static SingletonInit GetInstance() {
        return instance;
    }
}


代码示例三 饿汉式(静态代码块):

public class Singleton {

    private static Singleton instance;

    static {
        instance = new Singleton();
    }

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}


三、Strategy Pattern 策略模式(商场有多种优惠策略)
       概念:策略被适用于在同一算法有不同的实现或不同的操作方式,运行的时候会动态选择。通常来说,公共的方法在抽象类中实现,提供给子类能实现不同的行为。客户端通常可以查看不同的策略并选择使用它。

      个人理解:比较明显的例子,就是商场买衣服,3月份打8折,4月份打7折,6月份买一送一的活动方案。代码示例:

步骤一,提供策略类,定义所有的策略方案有共同的接口提供。

abstract class Strategy {
    public abstract void AlgorithmInterface();
}


步骤二,统一继承策略类,依次实现策略A、策略B、策略C

public class ConcreteStrategyA extends Strategy {
    @Override
    public void AlgorithmInterface() {
        System.out.println("新款商品,不参与活动");
    }
}


public class ConcreteStrategyB extends Strategy {
    @Override
    public void AlgorithmInterface() {
        System.out.println("符合活动条件满300返200");
    }
}


public class ConcreteStrategyC extends Strategy {
    @Override
    public void AlgorithmInterface() {
        System.out.println("符合活动条件,打8折");
    }
}


步骤三,创建策略工厂,包含哪些策略方案

public class Context {
    private Strategy strategy;
    public Context(String type) {
        switch (type) {                                 ----可以优化的方式,不需要用switch-case,变更办法是使用反射技术
            case "正常收费":
                strategy = new ConcreteStrategyA();
                break;
            case "满300返200":
                strategy = new ConcreteStrategyB();
                break;
            case "打8折":
                strategy = new ConcreteStrategyC();
                break;
        }
    }

    public void ContextInterface() {
        strategy.AlgorithmInterface();
    }
}

步骤四,商场人员选择策略,不需要让商场人员知道这个策略是哪个方法实现的

public class Test {
    public static void main(String[] args) {
        Context context;
        context = new Context("正常收费");
        context.ContextInterface();

        context = new Context("打8折");
        context.ContextInterface();

        context = new Context("满300返200");
        context.ContextInterface();
    }
}


输出结果:

新款商品,不参与活动
符合活动条件,打8折
符合活动条件满300返200

四、Template Pattern 模版模式(全国统考,保持试卷一致,修改变更)
       概念:模版模式是实现一个抽象类并经常被用于提供一个蓝图或大纲。有时候,也被使用于实现系统的钩子,例如一个应用程序框架。(中文水平不好哈)

  个人理解:比如创建一份统一试卷,提供给班级每个学生测试,学生在上面填写答案即可。试卷修改的时候,可以一次性把所有试卷的内容都修改。代码示例:

步骤一,创建试卷,并提供填写答案的方法Answer1、Answer2、Answer3。

abstract class TestPaper {
    public void TestQuestion1(){
        System.out.println("题目1,杨过来过,郭敬也来过,来了几个人?");
        System.out.println("答案:" + Answer1());
    }

    public void TestQuestion2(){
        System.out.println("题目1,小强来过,小明也来过,来了几个人?");
        System.out.println("答案:" + Answer2());
    }

    public void TestQuestion3(){
        System.out.println("题目1,小强走了,小明还在,还有几个人?");
        System.out.println("答案:" + Answer3());
    }

    public abstract String Answer1();
    public abstract String Answer2();
    public abstract String Answer3();
}


步骤二,学生A、学生B填写试卷

public class TestPaperA extends TestPaper {
    @Override
    public String Answer1() {
        return "B";
    }

    @Override
    public String Answer2() {
        return "C";
    }

    @Override
    public String Answer3() {
        return "A";
    }
}
public class TestPaperB extends TestPaper {
    @Override
    public String Answer1() {
        return "A";
    }

    @Override
    public String Answer2() {
        return "B";
    }

    @Override
    public String Answer3() {
        return "C";
    }
}


步骤三,给学生分发试卷,查看学生填写试卷结果

public class Test {
    public static void main(String[] args) {
        System.out.println("学生甲的开始试卷答题:");
        TestPaper testPaperA = new TestPaperA();
        testPaperA.TestQuestion1();
        testPaperA.TestQuestion2();
        testPaperA.TestQuestion3();

        System.out.println("学生乙的开始试卷答题:");
        TestPaper testPaperB = new TestPaperB();
        testPaperB.TestQuestion1();
        testPaperB.TestQuestion2();
        testPaperB.TestQuestion3();
    }
}


输出结果:

学生甲的开始试卷答题:
题目1,杨过来过,郭敬也来过,来了几个人?
答案:B
题目1,小强来过,小明也来过,来了几个人?
答案:C
题目1,小强走了,小明还在,还有几个人?
答案:A
学生乙的开始试卷答题:
题目1,杨过来过,郭敬也来过,来了几个人?
答案:A
题目1,小强来过,小明也来过,来了几个人?
答案:B
题目1,小强走了,小明还在,还有几个人?
答案:C

五、Abstract Factory Pattern 抽象工厂模式(服务端连接不同数据库),含反射用法示例
       概念:不同于单例模式。这个模式适用于运行时需要选择模式,并且该模式下包含不同的兼容类需要实例化处理。该模式在JAVA API中使用。

       个人理解:比如当需求变更,原先服务端访问的是ORACLE数据库,现在要替换成MYSQL、SQLSERVER等,会因为SQL语法做出重大和繁琐的改造工作。

代码示例:

步骤一,定义访问数据库表的统一接口方法(查询、插入)。

public interface IUser {
    void InsertUser(User user);

    User GetUser(Integer id);
}


步骤二,在SQL SERVER方式中,分别实现对User表和Department表的操作

public class SqlserverUser implements IUser {
    @Override
    public void InsertUser(User user) {
        System.out.println("在SQL SERVER中给User表新增一条记录");
    }

    @Override
    public User GetUser(Integer id){
        System.out.println("在SQL SERVER中根据ID得到User表一条记录");
        return null;
    }
}
public class SqlserverDepartment implements IDepartment {
    @Override
    public void InsertDeptment(Department department) {
        System.out.println("在SQL SERVER中给Deptment表新增一条记录");
    }

    @Override
    public Department GetDepartment(Integer id) {
        System.out.println("在SQL SERVER中根据ID得到Deptment表一条记录");
        return null;
    }
}


步骤三,在Access数据库方式中,分别实现对User表和Department表的操作

public class AccessUser implements IUser {
    @Override
    public void InsertUser(User user) {
        System.out.println("在Access中给User表新增一条记录");
    }

    @Override
    public User GetUser(Integer id) {
        System.out.println("在Access中根据ID得到User表一条记录");
        return null;
    }
}
public class AccessDepartment implements IDepartment {
    @Override
    public void InsertDeptment(Department department) {
        System.out.println("在Access中给Department表新增一条记录");
    }

    @Override
    public Department GetDepartment(Integer id) {
        System.out.println("在Access中根据ID得到Department表一条记录");
        return null;
    }
}


步骤四,创建简单的工厂模式类,其中注释部分大家可以看下,传统工厂模式的写法

这里采用反射的实现方法Class.forName(className).newInstance()

其中,className是包+类名称,newInstance()为实例化类

public class DataAccess {
    private static final String db = "Sqlserver";
    private static final String AssemblyName = "abstractfactory";

    public static IUser CreateUser() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//        IUser result = null;
//        switch (db) {
//            case "SqlServer":
//                result = new SqlserverUser();
//                break;
//            case "Access":
//                result = new AccessUser();
//                break;
//        }
//        return result;
        String className = AssemblyName + "." + db + "User";
        return (IUser)Class.forName(className).newInstance();
    }

    public static IDepartment CreateDepartment() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
//        IDepartment result = null;
//        switch (db) {
//            case "SqlServer":
//                result = new SqlserverDepartment();
//                break;
//            case "Access":
//                result = new AccessDepartment();
//                break;
//        }
//        return result;
        String className = AssemblyName + "." + db + "Department";
        return (IDepartment)Class.forName(className).newInstance();
    }
}


步骤五,选择数据库进行数据访问

public class FactoryTest {
    public static void main(String[] args) {
       //一般工厂模式
        User user = new User();
//        IFactory factory = new SqlServerFactory();                   ----选择数据库方式
        IFactory factory = new AccessFactory();
        IUser iUser = factory.CreateUser();
        iUser.InsertUser(user);
        iUser.GetUser(1);

        Department department = new Department();
        IDepartment iDepartment = factory.CreateDepartment();
        iDepartment.InsertDeptment(department);
        iDepartment.GetDepartment(1);

        //抽象工厂模式
        User user1 = new User();
        IUser iUser1 = null;
        try {
            iUser1 = DataAccess.CreateUser();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        iUser1.InsertUser(user1);
        iUser1.GetUser(1);

        Department department1 = new Department();
        IDepartment iDepartment1 = null;
        try {
            iDepartment1 = DataAccess.CreateDepartment();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        iDepartment1.InsertDeptment(department1);
        iDepartment1.GetDepartment(1);

    }
}


输出结果:

在Access中给User表新增一条记录
在Access中根据ID得到User表一条记录
在Access中给Department表新增一条记录
在Access中根据ID得到Department表一条记录
在SQL SERVER中给User表新增一条记录
在SQL SERVER中根据ID得到User表一条记录
在SQL SERVER中给Deptment表新增一条记录
在SQL SERVER中根据ID得到Deptment表一条记录


 

转载于:https://my.oschina.net/ydsakyclguozi/blog/3016459

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值