资讯专栏INFORMATION COLUMN

Java学习 - 设计模式

MorePainMoreGain / 1044人阅读

摘要:举例遇到多个构造器参数时考虑使用构建器,而不是重叠构造器模式或模式调用方法。静态工厂和构造器有个共同的局限性它们不能很好地扩展大量的可选参数构建器模式年月日客户端调用缺点构建器模式可能比重叠构造器更加冗长,参数多时使用较好。

设计模式

此文章部分来于网络,为了学习总结。

一、原型模式(Prototype)

介绍:从一个对象再创建另一个对象,而不需知道任何细节。

1、两种表现形式

(1)简单形式

(2)登记形式

这两种表现形式仅仅是原型模式的不同实现。

2、俩种克隆方法

(1)浅复制

介绍:只克隆值传递的数据(比如基本数据类型、String),而不复制它所引用的对象,就是对其他对象的引用都指向原来的对象。

注意:可实现Cloneable接口。

(2)深复制

介绍:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据,把要复制的对象所引用的对象都复制了一遍。

注意:采用字节流写入写出对象,所有对象必须实现Serializable。Thread和Socket对象必须设置transient,不予复制。
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Prototype implements Cloneable, Serializable{
    
    @Override
    protected Object clone() throws CloneNotSupportedException { //浅克隆
        // TODO Auto-generated method stub
        Prototype prototype = (Prototype) super.clone();
        return prototype;
    }
    
    public Object deepClone(){ //深克隆
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return ois.readObject();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        }
    }
    
}
二、模板方法模式

介绍:将重复的部分上升到父类。

举例:公司的面试题是相同的,只有应聘者的答案不同,所以相同的问题在父类中表现,子类只用作记录答案。

public class TestPaper {
    
    public void testQuestion1(){
        System.out.println("1 + 1 = ");
        System.out.println("答案是:" + answer());
    }
    
    protected String answer(){
        return "";
    }

}
public class TestPaperA extends TestPaper {
    
    @Override
    protected String answer() {
        // TODO Auto-generated method stub
        return "2";
    }

}
public class Client {
    
    public static void main(String[] args) {
        TestPaper testPagerA = new TestPaperA();
        testPagerA.question();        
    }
    
}
三、外观模式(Fade)

介绍:定义一个高层接口,使得子系统更容易使用。

四、建造者模式(Builder)

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

举例:遇到多个构造器参数时考虑使用构建器,而不是重叠构造器模式或JavaBean模式调用setter方法。(静态工厂和构造器有个共同的局限性:它们不能很好地扩展大量的可选参数)

/**
 * 构建器模式
 * @author alex
 * @date 2017年4月6日
 */
public class A {
    
    private final int a;
    private final int b;
    private final int c;
    
    public static class A_son {
        private final int a;
        private final int b;
        private int c = 0;
        
        public A_son(int a, int b) {
            this.a = a;
            this.b = b;
        }

        public A_son c(int val) { 
            c = val;
            return this;
        }
        
        public A build() {
            return new A(this);
        }
        
    }

    public A(A_son a_son) {
        a = a_son.a;
        b = a_son.b;
        c = a_son.c;
    }
    
}
A a = new A.A_son(12, 12).c(12).build(); //客户端调用

缺点:构建器模式可能比重叠构造器更加冗长,参数多时使用较好。如果构建器没有在最初使用,后期使用会有些难以控制,通常一开始就使用构建器。

优点:构建器比重叠构造器的客户端代码易读写。比JavaBean更安全。

五、观察者模式 六、工厂方法模式

举例:项目中可能需要访问多种类型的数据库,数据库访问与逻辑业务应该独立分开,只需在客户端创建工厂类。

七、抽象工厂模式

八、状态模式

介绍:将对象转换的逻辑判断转移到不同状态的类中,来简化复杂的逻辑判断。如果逻辑判断很简单就不需要用此模式了。

abstract class State {
    
    public abstract void handle(Context context);

}

public class Context {
    
    private State state;

    public Context(State state) {
        this.state = state;
    }
    
    public void request() {
        state.handle(this);
    }

    public State getState() {
        System.out.println("当前状态: " + state.getClass().toString());
        return state;
    }

    public void setState(State state) {
        this.state = state;
        getState();
    }
    
}

public class ConcreteStateA extends State {

    @Override
    public void handle(Context context) {
        // TODO Auto-generated method stub
        context.setState(new ConcreteStateB()); // 创建下一个逻辑判断
    }

}
public class ConcreteStateB extends State {

    @Override
    public void handle(Context context) {
        // TODO Auto-generated method stub
        context.setState(new ConcreteStateA());
    }

}

public class Test {
    
    public static void main(String[] args) {
        Context context = new Context(new ConcreteStateA());
        context.request();
        context.request();
        context.request();
    }

}
九、适配器模式

介绍:系统的数据和行为都正确,但接口不符时,使得一个原有对象与某个接口匹配。

举例:假如巴西队中有中国球员,防止语言间的差异,中国球员需要翻译来与团队交流。

十、备忘录模式

介绍:捕获一个对象的内部状态,并在该对象之外保存这个状态。之后可恢复之前的状态。

public class Originator {
    
    private String state;
    
    public Memento createMemento() {
        return new Memento(state);
    }
    
    public void setMemento(Memento memento) {
        state = memento.getState();
    }
    
    public void show() {
        System.out.println("state =" + state);
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
}

public class Caretaker {
    
    private Memento memento;

    public Memento getMemento() {
        return memento;
    }

    public void setMemento(Memento memento) {
        this.memento = memento;
    }
    
}

public class Memento {
    
    private String state;

    public Memento(String state) {
        this.state = state;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }
    
}

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Originator originator = new Originator();
        originator.setState("on");
        originator.show();
        
        Caretaker caretaker = new Caretaker();
        caretaker.setMemento(originator.createMemento());
        
        originator.setState("asdasd");
        originator.show();
        
        originator.setMemento(caretaker.getMemento());
        originator.show();
    }

}

缺点:易消耗内存。

十一、组合模式

介绍:将对象组合成树形结构来表示部分-整体,使部分与整体具有一致性。

public abstract class Component {

    protected String name;

    public Component(String name) {
        this.name = name;
    }
    
    public abstract void add(Component c);
    public abstract void remove(Component c);
    public abstract void display(int depth);
    
}

import org.apache.commons.lang.StringUtils;

public class Leaf extends Component {

    public Leaf(String name) {
        super(name);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void add(Component c) {
        // TODO Auto-generated method stub
        System.out.println("Don"t add component");
    }

    @Override
    public void remove(Component c) {
        // TODO Auto-generated method stub
        System.out.println("Don"t remove component");
    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(StringUtils.repeat("-", depth) + name);
    }

}

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

public class Composite extends Component {
    
    private List list = new ArrayList();

    public Composite(String name) {
        super(name);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void add(Component c) {
        // TODO Auto-generated method stub
        list.add(c);
    }

    @Override
    public void remove(Component c) {
        // TODO Auto-generated method stub
        list.remove(c);
    }

    @Override
    public void display(int depth) {
        // TODO Auto-generated method stub
        System.out.println(StringUtils.repeat("-", depth) + name);
        for (Component component : list) {
            component.display(depth + 2);
        }
    }

}

public class Test {
    
    public static void main(String[] args) {
        Composite root = new Composite("root");
        
        root.add(new Leaf("Leaf A"));
        root.add(new Leaf("Leaf B"));
        
        Composite comp = new Composite("Composite X");
        comp.add(new Leaf("Leaf XA"));
        comp.add(new Leaf("Leaf XB"));
        
        root.add(comp);
        
        Composite comp2 = new Composite("Composite Y");
        root .add(comp2);
        
        root.display(1);
    }

}
十二、迭代器模式

介绍:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示

/**
 * 迭代器抽象
 * @author chenguyan
 * @date 2017年6月16日
 */
public abstract class Iterator {
    
    public abstract Object first();
    public abstract Object next();
    public abstract boolean isDone();
    public abstract Object currentItem();

}

/**
 * 聚集抽象
 * @author chenguyan
 * @date 2017年6月16日
 */
public abstract class Aggregate {

    public abstract Iterator createIterator();

}

/**
 * 具体聚集
 * @author chenguyan
 * @date 2017年6月16日
 */
public class ConcreteAggregate extends Aggregate {

    private List items = new ArrayList();
    
    @Override
    public Iterator createIterator() {
        // TODO Auto-generated method stub
        return new ConcreteIterator(this);
    }
    
    public int count() {
        return items.size();
    }
    
    public Object get(int index) {
        return items.get(index);
    }
    
    public void add(Object obj) {
        items.add(obj);
    }

}

/**
 * 具体迭代器
 * @author chenguyan
 * @date 2017年6月16日
 */
public class ConcreteIterator extends Iterator {
    
    private ConcreteAggregate concreteAggregate;
    private int current = 0;
    
    public ConcreteIterator(ConcreteAggregate concrete) {
        // TODO Auto-generated constructor stub
        this.concreteAggregate = concrete;
    }

    @Override
    public Object first() {
        // TODO Auto-generated method stub
        return concreteAggregate.get(0);
    }

    @Override
    public Object next() {
        // TODO Auto-generated method stub
        current++;
        if (current >= concreteAggregate.count()) {
            return null;
        }
        return concreteAggregate.get(current);
    }

    @Override
    public boolean isDone() {
        // TODO Auto-generated method stub
        return current > concreteAggregate.count() ? true : false;
    }

    @Override
    public Object currentItem() {
        // TODO Auto-generated method stub
        return concreteAggregate.get(current);
    }

}

/**
 * 客户端
 * @author chenguyan
 * @date 2017年6月16日
 */
public class Client {
    
    public static void main(String[] args) {
        ConcreteAggregate concrete = new ConcreteAggregate();
        concrete.add("a");
        concrete.add("b");
        concrete.add("c");
        concrete.add("d");
        concrete.add("e");
        
        Iterator ite = new ConcreteIterator(concrete);
        
        System.out.println(ite.first().toString());
        
        while (!ite.isDone()) {
            Object item = ite.next();
            System.out.println(item != null ? item.toString() : "");
        }
    }

}

为什么会采用抽象类的方式来实现迭代器呢?因为可以有不同的迭代顺序,从前向后、从后向前等,所以随意新增迭代器的实现类来达到迭代顺序的不同,而且客户端修改部分较少。

十三、单例模式

介绍:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

/**
 * 双重锁定
 * @date 2017年7月3日
 */
public class Singleton {
    
    private static Singleton singleton;
    private static Object syncObj = new Object();
    
    public static Singleton getInstance() {
        if (singleton == null) {
            synchronized (syncObj) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }

}
十四、桥接模式

介绍:按各自的功能进行分类,使他们可以独立运行。

举例:手机的品牌与软件都会存在不兼容的情况,这是因为手机厂商即做硬件又做软件,没有统一的标准。如果有一个统一的硬件厂商设计标准,手机厂商只负责软件,这样每个手机厂商开发的软件就不存在不兼容的情况了。

十五、命令模式

介绍:将请求命令封装成对象,从而使你可用不同的请求命令来操作对象。

/**
 * 命令
 * @date 2017年8月11日
 */
public abstract class Command {
    
    private Recipient recipient;

    public void setRecipient(Recipient recipient) {
        this.recipient = recipient;
    }
    
    public abstract void doing();

}

/**
 * 烤菜命令
 * @date 2017年8月11日
 */
public class RoastVegetablesCommand extends Command {

    private Recipient recipient;
    
    @Override
    public void setRecipient(Recipient recipient) {
        // TODO Auto-generated method stub
        this.recipient = recipient;
    }
    
    @Override
    public void doing() {
        // TODO Auto-generated method stub
        System.out.println("正在烤菜");
    }
    
}

/**
 * 烤肉命令
 * @date 2017年8月11日
 */
public class RoastMeatCommand extends Command {
    
    private Recipient recipient;
    
    @Override
    public void setRecipient(Recipient recipient) {
        // TODO Auto-generated method stub
        this.recipient = recipient;
    }

    @Override
    public void doing() {
        // TODO Auto-generated method stub
        System.out.println("正在执行烤肉");
    }

}

/**
 * 接收人
 * @date 2017年8月11日
 */
public class Recipient {
    
    private String name;
    private String job;
    
    public Recipient(String name, String job) {
        this.name = name;
        this.job = job;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    
}

/**
 * 服务员
 * @date 2017年8月11日
 */
public class Waiter {
    
    private List commandList = new ArrayList();
    
    public void addOrder(Command command) {
        if (!commandList.contains(command)) {
            commandList.add(command);
        }
    }
    
    public void notifyCommand() {
        for (Command command : commandList) {
            command.doing();
        }
    }

}

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        
        Recipient recipient = new Recipient("大厨", "大厨");
        
        Command roastMeatCommand = new RoastMeatCommand();
        Command roastVegetablesCommand = new RoastVegetablesCommand();
        
        roastMeatCommand.setRecipient(recipient);
        roastVegetablesCommand.setRecipient(recipient);
        
        Waiter waiter = new Waiter();
        waiter.addOrder(roastMeatCommand);
        waiter.addOrder(roastVegetablesCommand);
        waiter.notifyCommand();
    }

}
设计原则 一、迪米特法则

介绍:如果两个类不必彼此通信,那么这两个类就不应当发生直接的相互作用。强调类之间的松耦合。

反射机制 一、调用私有域和方法(setAccessible)
class Employee{

    private int id;
    private String name;
    private int age;
    
    public Employee(){}
    
    public Employee(int id, String name, int age){
        this.id = id;
        this.name = name;
        this.age = age;
    }

    private void setId(int id){
       this.id = id;
    }
    
    private int judge(int id){
        return this.id - id;
    }
    
    private String sayHalo(String name){
        return "Halo" + name;
    }
    
}
public class PrivateTest{

     public static void main(String[] args){
         Employee em = new Employee(1, "Alex", 22);

         Class emClass =  em.getClass();
 
         Method judgeMethod = emClass.getDeclaredMethod("judge", new Class[]{Integer.TYPE}); //获取声明的方法
         judgeMethod.setAccessible(true); //使成员可以访问
 
         Method[] allMethods = emClass.getDeclaredMethods(); //获取所有声明的方法
         AccessibleObject.setAccessible(allMethods, true);
        
         judgeMethod.invoke(em, new Object[]{3}); //通过反射访问
 
         //or...
         for(Method method : allMethods){
          ...
         }
     }
     
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66917.html

相关文章

  • 学习Java必读的10本书籍

    摘要:学习编程的本最佳书籍这些书涵盖了各个领域,包括核心基础知识,集合框架,多线程和并发,内部和性能调优,设计模式等。擅长解释错误及错误的原因以及如何解决简而言之,这是学习中并发和多线程的最佳书籍之一。 showImg(https://segmentfault.com/img/remote/1460000018913016); 来源 | 愿码(ChainDesk.CN)内容编辑 愿码Slo...

    masturbator 评论0 收藏0
  • java 基础 - 收藏集 - 掘金

    摘要:基础知识复习后端掘金的作用表示静态修饰符,使用修饰的变量,在中分配内存后一直存在,直到程序退出才释放空间。将对象编码为字节流称之为序列化,反之将字节流重建成对象称之为反序列化。 Java 学习过程|完整思维导图 - 后端 - 掘金JVM 1. 内存模型( 内存分为几部分? 堆溢出、栈溢出原因及实例?线上如何排查?) 2. 类加载机制 3. 垃圾回收 Java基础 什么是接口?什么是抽象...

    makeFoxPlay 评论0 收藏0
  • Java架构体系学习路线图,第六点尤为重要!

    摘要:有不少朋友问,除了掌握语法,还要系统学习哪些相关的技术,今天分享一个,互联网技术学习路线图。群内已经有小伙伴将知识体系整理好源码,笔记,学习视频,欢迎加群免费取。 showImg(https://segmentfault.com/img/remote/1460000015926035); 我们都知道android依赖于Java,五六年后进入瓶颈期,很多人都学习了后台业务关的知识。当然我...

    hufeng 评论0 收藏0
  • java篇 - 收藏集 - 掘金

    摘要:进阶多线程开发关键技术后端掘金原创文章,转载请务必将下面这段话置于文章开头处保留超链接。关于中间件入门教程后端掘金前言中间件 Java 开发人员最常犯的 10 个错误 - 后端 - 掘金一 、把数组转成ArrayList 为了将数组转换为ArrayList,开发者经常... Java 9 中的 9 个新特性 - 后端 - 掘金Java 8 发布三年多之后,即将快到2017年7月下一个版...

    OpenDigg 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<