美文网首页
浅谈常用的设计模式

浅谈常用的设计模式

作者: Owen270 | 来源:发表于2018-09-18 16:48 被阅读8次
    参考文章:

    单例模式 https://www.cnblogs.com/hupp/p/4487521.html
    观察者模式 https://www.cnblogs.com/luohanguo/p/7825656.html
    装饰模式 https://blog.csdn.net/z4909801/article/details/59059263
    六大原则:https://www.jianshu.com/p/bf92927c9d22

    1.单例模式

    (1):懒汉(线程不安全,在多线程中无法正常工作)

      private SingleTon(){}
        private static SingleTon instance;
        public static SingleTon getInstance(){
            if(instance==null){
                instance=new SingleTon();
            }
            return instance;
        }
    

    (2):懒汉(线程··安全 synchronized同步函数)

    public class SingleTon {
        private SingleTon(){}
        private static SingleTon instance;
        public static synchronized SingleTon getInstance(){
            if(instance==null){
                instance=new SingleTon();
            }
            return instance;
        }
    }
    

    (3):懒汉(线程··安全 synchronized同步代码块,双重校验锁)

    public class SingleTon {
        private SingleTon(){}
        private static SingleTon instance;
        public static  SingleTon getInstance(){
            if(instance==null){
                synchronized (SingleTon.class){
                    if(instance==null){
                        instance=new SingleTon();
                    }
                }
            }
            return instance;
        }
    }
    

    (4).饿汉(一旦SingleTon 被装载了,instance会立马实例化)

    public class SingleTon {
        private SingleTon(){}
        private static SingleTon instance=new SingleTon();
        public static  SingleTon getInstance(){
            return instance;
        }
    }
    

    (5).饿汉(静态内部类,这种方式的好处是即使SingleTon被装载了,instance也不会立马实例化)

    public class SingleTon {
        private SingleTon(){}
        private static class SingleTonHolder {
            private static SingleTon instance=new SingleTon();
        }
        public static  SingleTon getInstance(){
            return SingleTonHolder.instance;
        }
    }
    

    2.工厂模式

    (1).普通工厂模式

    public interface Sender {
        public void send();
    }
    
    public class MailSender implements Sender{
        @Override
        public void send() {
            System.out.println("this is mail sender");
        }
    }
    
    public class SmsSender implements  Sender {
        @Override
        public void send() {
            System.out.println("this is sms sender");
        }
    }
    
    public class SendFactoryOne {
        public Sender produce(String type){
            if(type.equals("mail")){
                return  new MailSender();
            }else if(type.equals("sms")){
                return  new SmsSender();
            }else{
                return null;
            }
        }
    }
    
    

    (2).工厂方法模式

    public class SendFactoryTwo {
        public  Sender produceMail(){
           return new MailSender();
        }
        public  Sender produceSms(){
            return new SmsSender();
        }
    }
    

    (3).静态工厂方法模式

    public class SendFactoryThree {
        public static Sender produceMail(){
           return new MailSender();
        }
        public static Sender produceSms(){
            return new SmsSender();
        }
    }
    
    

    (4).抽象工程模式

    注意:工程方法模式有个问题,类的创建和扩展必须修改工厂类,这违背了闭包原则,所有用到抽象工厂模式,创建多个工厂类,这样一来,直接增加工厂类就可以了,不需要修改之前的代码。
    public interface Provider {
        public Sender produce();
    }
    
    public class SendMailFactory implements Provider {
        @Override
        public Sender produce() {
            return new MailSender();
        }
    }
    public class SendSmsFactory implements Provider {
        @Override
        public Sender produce() {
            return new SmsSender();
        }
    }
    public class MainTest {
        public static void main(String[] args){
            SendFactoryOne sendFactoryOne=new SendFactoryOne();
            sendFactoryOne.produce("mail");
            sendFactoryOne.produce("sms");
    
             SendFactoryTwo sendFactoryTwo=new SendFactoryTwo();
             sendFactoryTwo.produceMail();
             sendFactoryTwo.produceSms();
    
             SendFactoryThree.produceMail();
             SendFactoryThree.produceSms();
             
             Provider provider=new SendMailFactory();
             Sender sender=provider.produce();
             sender.send();
    
             Provider provider1=new SendSmsFactory();
             Sender sender1=provider1.produce();
             sender1.send();
        }
    }
    

    3.观察者模式

    类似于邮件订阅,当我们浏览一些博客或者wiki时,当你订阅了改文章,如果后续有更新,会及时通知你,是一种一对多的关系。(https://www.cnblogs.com/luohanguo/p/7825656.html
    (1) 、定义一个抽象观察者接口

    public interface Observer {
        public void update();
    }
    

    (2)、定义一个抽象被观察者接口

    public interface Observerable {
        public void registerObserver(Observer observer);
        public void removeObserver(Observer observer);
        public void notifyObservers();
    }
    

    (3).定义被观察者,实现了Observerable接口,对Observerable接口的三个方法进行了具体实现,同时有一个List集合,用以保存注册的观察者,等需要通知观察者时,遍历该集合即可,通知新增一个operation()用于通知所有的观察者。

    public class WeChatServer implements Observerable {
    
       List<Observer>  list=new ArrayList<>();//面向接口编程
    
        @Override
        public void registerObserver(Observer observer) {
            list.add(observer);
        }
    
        @Override
        public void removeObserver(Observer observer) {
            if(!list.isEmpty()){
                list.remove(observer);
            }
        }
    
        @Override
        public void notifyObservers() {
            for(int i=0;i<list.size();i++){
                list.get(i).update();
            }
        }
    
        public void operation() {
            notifyObservers();
        }
    }
    

    (4)、定义具体观察者,微信公众号的具体观察者为用户User1,User2

    public class User1 implements Observer {
        @Override
        public void update() {
            System.out.println(User1.class.toString() +"has received the push message!");
        }
    }
    public class User2 implements Observer {
        @Override
        public void update() {
            System.out.println(User2.class.toString() +"has received the push message!");
        }
    }
    
    

    (5)、编写一个测试类

    public class MainTest {
        public static void main(String[] args){
            WeChatServer server=new WeChatServer();
            User1 user1=new User1();
            User2 user2=new User2();
            server.registerObserver(user1);
            server.registerObserver(user2);
            server.operation();
        }
    }
    
    image.png

    4.装饰模式

    装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现统一接口或者继承同一个父类,装饰对象持有被装饰对象的实例。
    (1).Food类,让其他所有食物都来继承这个类

    public class Food {
        private String food_name;
        public Food(){
    
        }
        public Food(String food_name) {
            this.food_name = food_name;
        }
        public String make(){
            return  food_name;
        }
    }
    

    (2).Bread类,Cream类,Vegetable类

    public class Bread extends Food{
        private Food basic_food;
        public Bread(Food basic_food){
              this.basic_food=basic_food;
        }
        @Override
        public String make() {
            return basic_food.make()+"+面包";
        }
    }
    
    public class Cream extends Food {
        private  Food basic_food;
    
        public Cream(Food basic_food) {
            this.basic_food = basic_food;
        }
    
        @Override
        public String make() {
            return basic_food.make()+"+奶油";
        }
    }
    
    public class Vegetable extends Food {
        private Food basic_food;
    
        public Vegetable(Food basic_food) {
            this.basic_food = basic_food;
        }
    
        @Override
        public String make() {
            return basic_food.make()+"+蔬菜";
        }
    }
    
    

    (3).编写一个测试类

    public class MainTest {
    
        public static void main(String[] args){
            Food food=new Food("香肠");
            Bread bread=new Bread(food);
            Cream cream=new Cream(bread);
            Vegetable vegetable=new Vegetable(cream);
            System.out.print("运行结果:"+vegetable.make()+"\n");
        }
    }
    
    image.png

    5.适配器模式

    (1).类适配器模式(通过继承来实现适配器功能)

    我们以ps2与usb的转接为例:
    Ps2接口:

    public interface Ps2 {
        void isPs2();
    }
    

    Usb接口:

    public interface Usb {
        void isUsb();
    }
    

    Usb接口实现类:Usber

    public class Usber implements Usb {
        @Override
        public void isUsb() {
    
        }
    }
    

    适配器:AdapterOne

    public class AdapterOne extends Usber implements Ps2{
        @Override
        public void isPs2() {
               isUsb();
        }
    }
    

    测试方法:

     public static void main(String[] args){
            //1.类适配,通过继承类适配
            Ps2 p=new AdapterOne();
            p.isPs2();
        }
    
    (2).对象适配器模式(通过组合来实现适配器的功能)

    适配器:AdapterTwo

    public class AdapterTwo implements Ps2{
        private Usber usber;
        public AdapterTwo(Usber usber) {
            this.usber = usber;
        }
        @Override
        public void isPs2() {
            usber.isUsb();
        }
    }
    

    测试方法:

    public class MainTest {
        public static void main(String[] args){
            //2.对象适配,通过组合实现
            Ps2 p=new AdapterTwo(new Usber());
            p.isPs2();
        }
    }
    
    注意:类适配和对象适配模式中所有的adapter均需要实现Ps2接口
    (3).接口适配器模式(通过抽象类来实现)

    目标接口A:

    public interface A {
        void a();
        void b();
        void c();
        void d();
        void e();
    }
    

    A的实现类:Adapter

    public abstract class Adapter implements A {
        @Override
        public void a() {
    
        }
    
        @Override
        public void b() {
    
        }
    
        @Override
        public void c() {
    
        }
    
        @Override
        public void d() {
    
        }
    
        @Override
        public void e() {
    
        }
    }
    
    

    继承自Adapter的MyAdapter:

    public class MyAdapter extends Adapter {
    
        @Override
        public void a() {
            super.a();
            System.out.println("实现A方法");
        }
    
        @Override
        public void b() {
            super.b();
            System.out.println("实现B方法");
        }
    }
    

    测试方法:

      public static void main(String[] args){
            //3.接口适配,通过抽象类实现
            A aRealize=new MyAdapter();
            aRealize.a();
            aRealize.b();
    
        }
    

    6.策略模式(一个人走楼梯上楼或者走电梯上楼)

    这里以加减算法为例:
    (1).定义抽象策略角色接口:Strategy

    public interface Strategy {
         int calc(int num1,int num2);
    }
    

    (2).定义加法策略:AddStrategy

    public class AddStrategy implements Strategy{
        @Override
        public int calc(int num1, int num2) {
            return num1+num2;
        }
    }
    

    (3).定义减法策略:SubStrategy

    public class SubStrategy implements Strategy {
        @Override
        public int calc(int num1, int num2) {
            return num1-num2;
        }
    }
    

    (4).环境角色:Environment

    public class Environment {
        private Strategy strategy;
        public Environment(Strategy strategy) {
            this.strategy = strategy;
        }
    
        public int calc(int a,int b){
            return strategy.calc(a,b);
        }
    }
    

    测试方法:

     public static void main(String[] args){
            Strategy addStrage=new AddStrategy();
            Environment environment=new Environment(addStrage);
            int sum1=environment.calc(10,10);
            System.out.println("Result1:"+sum1);
            Strategy subStrage=new SubStrategy();
            int sum2=subStrage.calc(20,10);
            System.out.println("Result2:"+sum2);
        }
    

    7.Builder模式

    public class Request {
        private String name;
        private String reason;
        private String days;
        private String groupLeaderInfo;
        private String managerInfo;
        private String departmentHeaderInfo;
        private String customInfo;
        public Request(Builder builder){
             // super();
              this.name=builder.name;
              this.reason=builder.reason;
              this.days=builder.days;
              this.groupLeaderInfo=builder.groupLeaderInfo;
              this.managerInfo=builder.managerInfo;
              this.departmentHeaderInfo=builder.departmentHeaderInfo;
              this.customInfo=builder.customInfo;
    
        }
    
    
        public static class Builder{
            private String name;
            private String reason;
            private String days;
            private String groupLeaderInfo;
            private String managerInfo;
            private String departmentHeaderInfo;
            private String customInfo;
    
            public Builder setName(String name) {
                this.name = name;
                return this;
            }
    
            public Builder setReason(String reason) {
                this.reason = reason;
                return this;
            }
    
            public Builder setDays(String days) {
                this.days = days;
                return this;
            }
    
            public Builder setGroupLeaderInfo(String groupLeaderInfo) {
                this.groupLeaderInfo = groupLeaderInfo;
                return this;
            }
    
            public Builder setManagerInfo(String managerInfo) {
                this.managerInfo = managerInfo;
                return this;
            }
    
            public Builder setDepartmentHeaderInfo(String departmentHeaderInfo) {
                this.departmentHeaderInfo = departmentHeaderInfo;
                return this;
            }
    
            public Builder setCustomInfo(String customInfo) {
                this.customInfo = customInfo;
                return this;
            }
            public Builder newRequest(Request request){
                this.name=request.name;
                this.days=request.days;
                this.reason=request.reason;
                if(request.getGroupLeaderInfo()!=null&&!request.getGroupLeaderInfo().equals("")){
                    this.groupLeaderInfo=request.groupLeaderInfo;
                }
                if(request.getManagerInfo()!=null&&!request.getManagerInfo().equals("")){
                    this.managerInfo=request.managerInfo;
                }
                if(request.getDepartmentHeaderInfo()!=null&&!request.getDepartmentHeaderInfo().equals("")){
                    this.departmentHeaderInfo=request.getDepartmentHeaderInfo();
                }
                return this;
            }
    
            public Request build(){
                return new Request(this);
            }
        }
    
        public String getName() {
            return name;
        }
    
        public String getReason() {
            return reason;
        }
    
        public String getDays() {
            return days;
        }
    
        public String getGroupLeaderInfo() {
            return groupLeaderInfo;
        }
    
        public String getManagerInfo() {
            return managerInfo;
        }
    
        public String getDepartmentHeaderInfo() {
            return departmentHeaderInfo;
        }
    
        public String getCustomInfo() {
            return customInfo;
        }
    
        @Override
        public String toString() {
            return "Request{" +
                    "name='" + name + '\'' +
                    ", reason='" + reason + '\'' +
                    ", days='" + days + '\'' +
                    ", groupLeaderInfo='" + groupLeaderInfo + '\'' +
                    ", managerInfo='" + managerInfo + '\'' +
                    ", departmentHeaderInfo='" + departmentHeaderInfo + '\'' +
                    ", customInfo='" + customInfo + '\'' +
                    '}';
        }
    }
    

    测试方法:

      public static void main(String[] args){
           Request request=new Request.Builder()
                   .setName("shuijian")
                   .setReason("GoHome")
                   .setDays("2days")
                   .build();
           System.out.println(request.toString());
        }
    

    8.责任链模式

    实例场景
    在公司内部员工请假一般情况是这样的:员工在OA系统中提交一封请假邮件,该邮件会自动转发到你的直接上级领导邮箱里,如果你的请假的情况特殊的话,该邮件也会转发到你上级的上级的邮箱,根据请假的情况天数多少,系统会自动转发相应的责任人的邮箱。我们就以这样一种场景为例完成一个责任链模式的代码。为了更清晰的描述这种场景我们规定如下:
    ① GroupLeader(组长 ):他能批准的假期为2天,如果请假天数超过2天就将请假邮件自动转发到组长和经理邮箱。
    ② Manager(经理):他能批准的假期为4天以内,如果请假天数大于4天将该邮件转发到自动转发到组长、经理和部门领导的邮箱。
    ③ DepartmentHeader(部门领导):他能批准的假期为7天以内,如果大于7天就只批准7天。

    (1).构造Request对象,如:Builder模式中的Request
    (2).构造批准结果对象Result
    public class Result {
        public boolean isRality;
        public String  info;
    
        public Result(boolean isRality, String info) {
            this.isRality = isRality;
            this.info = info;
        }
    
        public boolean isRality() {
            return isRality;
        }
    
        public void setRality(boolean rality) {
            isRality = rality;
        }
    
        public String getInfo() {
            return info;
        }
    
        public void setInfo(String info) {
            this.info = info;
        }
    
        @Override
        public String toString() {
            return "Result{" +
                    "isRality=" + isRality +
                    ", info='" + info + '\'' +
                    '}';
        }
    }
    
    (3).定义一个接口,这个接口用于处理Request和获取请求结果Result
    public interface Ratify {
        //处理请求
        public Result deal(Chain chain);
        //对request和result封装,用来转发
        interface Chain{
            //获取当前的request
            Request request();
            //转发Request
            Result proceed(Request request);
        }
    }
    

    看到上面的接口,可能会有人迷惑:在接口Ratify中为什么又定义一个Chain接口呢?其实这个接口是单独定义还是内部接口没有太大关系,但是考虑到Chain接口与Ratify接口的关系为提高内聚性就定义为内部接口了。定义Ratify接口是为了处理Request那为什么还要定义Chain接口呢?这正是责任链接口的精髓之处:转发功能及可动态扩展“责任人”,这个接口中定义了两个方法一个是request()就是为了获取request,如果当前Ratify的实现类获取到request之后发现自己不能处理或者说自己只能处理部分请求,那么他将自己的那部分能处理的就处理掉,然后重新构建一个或者直接转发Request给下一个责任人。可能这点说的不容易理解,我举个例子,在Android与后台交互中如果使用了Http协议,当然我们可能使用各种Http框架如HttpClient、OKHttp等,我们只需要发送要请求的参数就直接等待结果了,这个过程中你可能并没有构建请求头,那么框架帮你把这部分工作给做了,它做的工程中如果使用了责任链模式的话,它肯定会将Request进行包装(也就是添加请求头)成新的Request,我们姑且加他为Request1,如果你又希望Http做本地缓存,那么Request1又会被转发到并且重新进一步包装为Request2。总之Chain这个接口就是起到对Request进行重新包装的并将包装后的Request进行下一步转发的作用。如果还不是很明白也没关系,本实例会演示这一功能机制。

    (4).实现Chain接口的的真正的包装Request和转发功能
    public class RealChain implements Ratify.Chain {
        public Request request;
        public List<Ratify> ratifyList;
        public int index;
        /**
         * 构造方法
         *
         * @param ratifyList
         *            Ratify接口的实现类集合
         * @param request
         *            具体的请求Request实例
         * @param index
         *            已经处理过该request的责任人数量
         */
        public RealChain(List<Ratify> ratifyList, Request request,int index) {
            this.request = request;
            this.ratifyList = ratifyList;
            this.index = index;
        }
        /**
         * 方法描述:具体转发功能
         */
        @Override
        public Result proceed(Request request) {
            Result proceed=null;
            if(ratifyList.size()>index){
              RealChain realChain=new RealChain(ratifyList,request,index+1);
              Ratify ratify=ratifyList.get(index);
              proceed=ratify.deal(realChain);
            }
            return proceed;
        }
    
        /***
         * 方法描述:返回当前Request对象或者返回当前进行包装后的Request对象
         * @return
         */
        @Override
        public Request request() {
            return request;
        }
    }
    
    (5).GroupLeader、Manager和DepartmentHeader,并让他们实现Ratify接口
    public class GroupLeader implements Ratify {
        @Override
        public Result deal(Chain chain) {
            Request request=chain.request();
            System.out.println("GroupLeader====>request:"+request.toString());
            if(Integer.parseInt(request.getDays())>1){
                //包装新的Request对象
                Request newRequest=new Request.Builder().newRequest(request).setGroupLeaderInfo(request.getName()+"平时表现不错,而且现在项目不忙").build();
                return chain.proceed(newRequest);
            }
            return new Result(true,"GroupLeader:早去早回");
        }
    }
    
    public class Manager implements Ratify {
        @Override
        public Result deal(Chain chain) {
            Request request=chain.request();
            System.out.println("Manager====>request:"+request.toString());
            if(Integer.parseInt(request.getDays())>3){
                //构建新的Request
                Request newRequest=new Request.Builder().newRequest(request).setManagerInfo(request.getName()+"每月的KPI考核还不错,可以批准").build();
                return chain.proceed(newRequest);
    
            }
            return new Result(true,"Manager:早点把事情办完,项目离不开你");
        }
    }
    
    public class DepartmentHeader implements Ratify {
        @Override
        public Result deal(Chain chain) {
            Request request=chain.request();
            System.out.println("DepartmentHeader=====>request:"+request.toString());
            if(Integer.parseInt(request.getDays())>7){
                  return  new Result(false,"DepartmentHeader:你这个时间太长,不能批准");
            }
            return new Result(true,"DepartmentHeader:不要着急,把事情处理完在回来!");
        }
    }
    
    public class CustomInterceptor implements Ratify {
        @Override
        public Result deal(Chain chain) {
            Request request=chain.request();
            System.out.println("CustomInterceptor====>"+request.toString());
            String reason=request.getReason();
            if(reason!=null&&reason.equals("事假")){
                  Request newRequest=new Request.Builder().newRequest(request).setCustomInfo(request.getName()+"请的是事假,而且很着急,请领导重视一下").build();
                  System.out.println("CustomInterceptor====>转发请求");
                  return chain.proceed(newRequest);
            }
            return new Result(true,"同意请假");
        }
    }
    
    (6).责任链模式工具类
    public class ChainOfResponsibilityClient {
        private ArrayList<Ratify> ratifies;
    
        public ChainOfResponsibilityClient() {
            ratifies=new ArrayList<>();
        }
    
        /**
         * 为了展示“责任链模式”的真正的迷人之处(可扩展性),在这里构造该方法以便添加自定义的“责任人”
         * @param ratify
         */
        public void addRatifys(Ratify ratify){
            ratifies.add(ratify);
        }
    
        /***
         *
         * 方法描述:执行请求
         * @param request
         * @return
         */
    
        public Result execute(Request request){
            ArrayList<Ratify> arrayList=new ArrayList<>();
            arrayList.addAll(ratifies);
            arrayList.add(new GroupLeader());
            arrayList.add(new Manager());
            arrayList.add(new DepartmentHeader());
            RealChain realChain=new RealChain(arrayList,request,0);
            return realChain.proceed(request);
        }
    }
    
    (6).测试方法
     public static void main(String[] args){
            //写法一
            Request.Builder builder=new Request.Builder();//通过静态内部类构建builder对象
            builder.setName("zhangsan");
            builder.setDays("5");
            builder.setReason("事假");
            Request request=builder.build();//build方法返回request对象
            //写法二
            Request request1=new Request.Builder().setName("lisi").setDays("7").setReason("事假").build();
            //System.out.print("结果:"+request.toString());
    
            ChainOfResponsibilityClient client=new ChainOfResponsibilityClient();
            //添加自定义的拦截器到责任人列表顶端
            client.addRatifys(new CustomInterceptor());
            Result result=client.execute(request);
            System.out.println("结果:"+result.toString());
    
        }
    

    9.享元模式

    (1).定义一个接口作为享元角色

    public interface IBike {
        void ride(int hours);
    }
    

    (2).实现IBike接口,作为具体的享元角色

    public class ShareBike implements IBike{
        private int price=2 ;
    
        @Override
        public void ride(int hours) {
            int total=2*hours;
            System.out.println("ride bike total spend "+total+" RMB");
    
        }
    }
    

    (3).创建享元工厂

    public class ShareBikeFactory {
        Map<String,IBike> pool=new HashMap<>();
        public  IBike getBike(String name){
            IBike iBike=null;
            if(!pool.containsKey(name)){
                iBike=new ShareBike();
                pool.put(name,iBike);
                System.out.println("交了199元押金,可以用车:"+name);
            }else{
                iBike=pool.get(name);
                System.out.println("押金已交,直接用车:"+name);
            }
            return iBike;
        }
    }
    

    (4).测试类

     public static void main(String[] args) {
            ShareBikeFactory shareBikeFactory=new ShareBikeFactory();
            //第一次骑ofo,交押金
            IBike ofo1=shareBikeFactory.getBike("ofo");
            ofo1.ride(2);
            //第一次骑mobike,交押金
            IBike mobike=shareBikeFactory.getBike("mobike");
            mobike.ride(3);
            //第二次骑mobike,不交押金
            IBike ofo2=shareBikeFactory.getBike("ofo");
            ofo2.ride(4);
        }
    

    10.模板方法模式

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

    public abstract class Postman {
    
        public final void post(){//这里声明为final,不希望子类覆盖这个方法,防止更改流程
            prepare();
            call();
            if(isSign()){
                sign();
            }else{
                refuse();
            }
        }
    
        protected void refuse() {
        }
    
        protected void sign() {
            System.out.println("派送完毕,客户已经签收!");
        }
    
        protected boolean isSign() {
            return true;
        }
    
        protected abstract void call();
    
        protected void prepare() {
            System.out.println("快递已经到达,准备派送...");
        }
    }
    

    需要注意的是上面的抽象类(Postman)包含了三种类型的方法:抽象方法、具体方法和钩子方法。
    抽象方法:需要子类去实现。如上面的call()。
    具体方法:抽象父类中直接实现。如上面的prepare()和sign()。
    钩子方法:有两种,第一种,它是一个空实现的方法,子类可以视情况来决定是否要覆盖它,如上面的refuse();第二种,它的返回类型通常是boolean类型的,一般用于对某个条件进行判断,如果条件满足则执行某一步骤,否则将不执行,如上面的isSign()。
    (2).创建具体实现类,定义算法框架
    PostmanA:

    public  class PostmanA extends Postman{
        @Override
        protected void call() {
            System.out.println("联系收货人A,准备派送...");
        }
    }
    

    PostmanB:

    public  class PostmanB extends Postman{
        @Override
        protected void call() {
            System.out.println("联系收货人B,准备派送...");
        }
    
        @Override
        protected boolean isSign() {
            return false;
        }
    
        @Override
        protected void refuse() {
            super.refuse();
            System.out.println("商品与实物不符,拒绝签收!");
        }
    }
    

    (3).测试类

     public static void main(String[] args){
            //A收货人正常签收
            Postman postmanA=new PostmanA();
            postmanA.post();
            //B收货人拒绝签收
            Postman postmanB=new PostmanB();
            postmanB.post();
        }
    
    image.png

    11.备忘录模式

    以游戏存档为例:
    (1).创建发起人角色:Game

    public class Game {
        private int mLevel=0;
        private int mIcon=0;
    
        /***
         * 开始游戏
         */
        public void paly(){
            System.out.print("升级了");
            mLevel++;
            System.out.println("当前等级为:"+mLevel);
            mIcon+=32;
            System.out.println("获得金币:"+mIcon);
            System.out.println("当前金币数量为:"+mIcon);
        }
    
        /***
         * 退出游戏
         */
        public void exit(){
            System.out.println("退出游戏,属性为:等级="+mLevel+",金币="+mIcon);
        }
    
        //创建备忘录
        public Memo createMemo(){
            Memo memo=new Memo();
            memo.setmLevel(mLevel);
            memo.setmIcon(mIcon);
            return memo;
        }
    
        public void setMemo(Memo memo){
            mLevel=memo.getmLevel();
            mIcon=memo.getmIcon();
        }
    
    }
    

    (2).创建备忘录角色:Memo

    public class Memo {
        private int mLevel;//等级
        private int mIcon;//金币数量
    
        public int getmLevel() {
            return mLevel;
        }
    
        public void setmLevel(int mLevel) {
            this.mLevel = mLevel;
        }
    
        public int getmIcon() {
            return mIcon;
        }
    
        public void setmIcon(int mIcon) {
            this.mIcon = mIcon;
        }
    }
    

    (3).创建负责人角色:CreateMemo

    public class CreateMemo {
        private Memo memo;
    
        public Memo getMemo() {
            return memo;
        }
    
        public void setMemo(Memo memo) {
            this.memo = memo;
        }
    }
    

    (4).测试类

    public static void main(String[] args){
            Game game=new Game();
            game.paly();
            CreateMemo createMemo=new CreateMemo();
            createMemo.setMemo(game.createMemo());//游戏存档
            game.exit();
            //第二次进入游戏
            System.out.println("第二次进入游戏");
            Game secondGame=new Game();
            secondGame.setMemo(createMemo.getMemo());//取出之前备忘录中的数据
            secondGame.paly();
            secondGame.exit();
        }
    

    12.原型模式

    (1).创建具体原型类
    实现Cloneable接口:

    public class Card implements Cloneable {
        private int num;//卡号
        private Spec spec=new Spec();
        public Card(){
            System.out.println("Card 执行构造函数");
        }
    
        @Override
        protected Card clone() throws CloneNotSupportedException {
            System.out.println("clone时不执行构造函数");
            Card card= (Card) super.clone();
            card.spec=spec.clone();//对Spce对象也调用clone,实现深拷贝
            return card;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public Spec getSpec() {
            return spec;
        }
    
        public void setSpec(int width,int  length) {
            spec.width=width;
            spec.length=length;
        }
    
        public class Spec implements Cloneable{
            private int width;
            private int length;
    
            public int getWidth() {
                return width;
            }
    
            public void setWidth(int width) {
                this.width = width;
            }
    
            public int getLength() {
                return length;
            }
    
            public void setLength(int length) {
                this.length = length;
            }
    
            @Override
            protected Spec clone() throws CloneNotSupportedException {
                return (Spec) super.clone();
            }
        }
    
        @Override
        public String toString() {
            return "Card{" +
                    "num=" + num +
                    ", spec=" +"{width="+spec.getWidth()+",length="+spec.getLength()+
                    '}';
        }
    }
    

    (2).测试类

     public static void main(String[] args) throws CloneNotSupportedException {
            Card card1=new Card();
            card1.setNum(111);
            card1.setSpec(66,67);
            System.out.println(card1.toString());
            System.out.println("---------------------");
            //拷贝
            Card card2=card1.clone();
            System.out.println(card2.toString());
            System.out.println("---------------------");
            //拷贝之后,card2对num进行重新赋值
            card2.setNum(222);
            System.out.println(card1.toString());
            System.out.println(card2.toString());
            System.out.println("---------------------");
            //拷贝之后,card2对Spec进行重新赋值之后,连card1也跟着改变了,这种就是浅拷贝
            card2.setSpec(76,77);
            System.out.println(card1.toString());
            System.out.println(card2.toString());
            System.out.println("---------------------");
        }
    
    image.png

    13.命令模式

    (1).创建命令接口Command

    public interface Command {
        void execute();
    }
    

    (2).创建命令接口实现类:ShutDownCommand

    public class ShutDownCommand implements Command {
        Receiver receiver;
    
        public ShutDownCommand(Receiver receiver) {
            this.receiver = receiver;
        }
    
        @Override
        public void execute() {
            System.out.println("命令角色执行关机命令");
            receiver.action();
        }
    }
    

    (3).创建命令执行者Receiver

    public class Receiver {
        public void action(){
            System.out.println("接收者执行具体的操作");
            System.out.println("开始执行关机命令");
            System.out.println("退出所有程序");
            System.out.println("关机...");
        }
    }
    

    (4).创建调用者Invoker

    public class Invoker {
        private  Command command;
        public Invoker(Command command) {
            this.command = command;
        }
        public void action(){
            System.out.println("调用者执行命令");
            command.execute();
        }
    }
    

    测试方法:

    public static void main(String[] args){
           Receiver receiver=new Receiver();//创建命令接收者
           Command command=new ShutDownCommand(receiver);//创建一个命令的具体实现对象,并指定命令接收者
           Invoker invoke=new Invoker(command);//创建一个命令调用者,并指定具体命令
           invoke.action();
        }
    
    注意:此处调用者与接受者之间的解藕。易于扩展,扩展命令只需新增具体命令类即可,符合开放封闭原则。
    image.png

    14.代理模式

    (1).静态代理
    IBuy接口

    public interface IBuy {
        void buy();
    }
    

    IBuy接口实现类:Demestic,OverSea

    public class Demestic implements IBuy {
        @Override
        public void buy() {
            System.out.println("国内要买一个包");
        }
    }
    
    public class Oversea implements IBuy {
        IBuy buyer;
        public Oversea(IBuy buyer) {
            this.buyer=buyer;
        }
    
        @Override
        public void buy() {
            System.out.println("我是海外代购");
            buyer.buy();
        }
    }
    

    测试方法:

      public static void main(String[] args){
            //静态代理
            IBuy demestic=new Demestic();
            IBuy oversea=new Oversea(demestic);
            oversea.buy();
            System.out.println("----------------------------------------");
            
        }
    
    

    (2).动态代理(代理类在程序运行时动态生成)
    动态代理类:DynamicProxy

    public class DynamicProxy implements InvocationHandler {
        private Object obj;//被代理的对象
        public DynamicProxy(Object obj) {
            this.obj=obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("海外动态代理调用方法:"+method.getName());
            Object result=method.invoke(obj,args);
            return result;
        }
    }
    

    测试方法:

      public static void main(String[] args){
            //动态代理
            IBuy demestics=new Demestic();//被代理类
            ClassLoader classLoader=demestics.getClass().getClassLoader();//获取classloader
            Class[] classes=new Class[]{IBuy.class};//接口类的class数组
            DynamicProxy dynamicProxy=new DynamicProxy(demestics);//创建动态代理
            IBuy oversea1= (IBuy) Proxy.newProxyInstance(classLoader,classes,dynamicProxy);
            oversea1.buy();//调用海外代购的buy,此处实际上是调用dynamicProxy.invoke()方法
            System.out.println("----------------------------------------");
    
        }
    
    image.png

    相关文章

      网友评论

          本文标题:浅谈常用的设计模式

          本文链接:https://www.haomeiwen.com/subject/nswpnftx.html