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

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

目录

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

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

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

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

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


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

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

      英文原版(来至JAVA-DESIGN-PATTERNS):A Proxy is a direct stand-in for another class, and it typically has the same interface as that class because it implements a common interface or an abstract class. The client object is not aware that it is using a proxy. A Proxy is used when access to the class the client would like to use must be mediated in a way that is apparent to the client -- because it requires restricted access or is a remote process, for example.

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

        (图示:COPY至大话设计模式,自己懒得画了)

    代码示例:

步骤一,定义共同的接口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 单例模式(不需要多次实例化某对象,节省资源消耗)

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

      英文原版(来至JAVA-DESIGN-PATTERNS):The Singleton pattern, for example, is used to encapsulate the creation of an object in order to maintain control over it. This not only ensures that only one is created, but also allows lazy instantiation; that is, the instantiation of the object can be delayed until it is actually needed.This is especially beneficial if the constructor needs to perform a costly operation, such as accessing a remote database.

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

(图示:COPY至大话设计模式,自己懒得画了)

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

步骤一,创建单例对象,对外仅提供访问实例化的对象方法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 SingletonStatic {
    private SingletonStatic(){

    }

    private static class SingletonHolder{
        private static SingletonStatic instance = new SingletonStatic();
    }

    public SingletonStatic GetInstance(){
        return SingletonHolder.instance;
    }
}

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

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

      英文原版(来至JAVA-DESIGN-PATTERNS):Strategy is used to allow different implementations of an algorithm, or operation, to beselected dynamically at run time. Typically, any common behavior is implemented in an abstract class and concrete subclasses provide the behavior that differs. The client is generally aware of the different strategies that are available and can choose between them.

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

(图示:COPY至大话设计模式,自己懒得画了)

代码示例:

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

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 模版模式(全国统考,保持试卷一致,修改变更)

       概念模版模式是实现一个抽象类并经常被用于提供一个蓝图或大纲。有时候,也被使用于实现系统的钩子,例如一个应用程序框架。(中文水平不好哈)

      英文原版(来至JAVA-DESIGN-PATTERNS):The Template pattern is implemented as an abstract class and it is often used to provide a blueprint or an outline for concrete subclasses. Sometimes this is used to implement hooks in a system, such as an application framework.

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

(图示:COPY至大话设计模式,自己懒得画了)

代码示例:

步骤一,创建试卷,并提供填写答案的方法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中使用。(中文水平不好哈)

      英文原版(来至JAVA-DESIGN-PATTERNS):In addition to the Singleton pattern, another common example of a creational pattern is the Factory Method. This pattern is used when it must be decided at run time which one of
several compatible classes is to be instantiated. This pattern is used throughout the Java API. 

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

(图示:COPY至大话设计模式,自己懒得画了)

代码示例:

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

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表一条记录

猜你喜欢

转载自blog.csdn.net/feixiang3447/article/details/81671448