কোড ডিজাইন: স্বেচ্ছাসেবী কার্যাদি ডেলিগেশন


9

পিপিসিগুলিতে, আমাদের প্রায়শই হিলের কিং অফ চ্যালেঞ্জ থাকে, যা একে অপরের বিরুদ্ধে বিভিন্ন কোড বট দেয়। আমরা এই চ্যালেঞ্জগুলিকে একক ভাষায় সীমাবদ্ধ রাখতে পছন্দ করি না, তাই আমরা স্ট্যান্ডার্ড I / O এর উপরে ক্রস-প্ল্যাটফর্ম যোগাযোগ করি।

আমার লক্ষ্য হ'ল একটি ফ্রেমওয়ার্ক লিখুন যা চ্যালেঞ্জ-লেখকরা এই চ্যালেঞ্জগুলি আরও সহজ করে তুলতে সক্ষম হবেন। আমি নিম্নলিখিত প্রয়োজনীয়তাগুলি পূরণ করতে চাই:

  1. চ্যালেঞ্জ-লেখক একটি শ্রেণি তৈরি করতে সক্ষম হন যেখানে পদ্ধতিগুলি প্রতিটি স্বতন্ত্র যোগাযোগের প্রতিনিধিত্ব করে । উদাহরণস্বরূপ, আমাদের গুড বনাম এভিল চ্যালেঞ্জের উপর, লেখক একটি Playerক্লাস তৈরি করবেন যার একটি abstract boolean vote(List<List<Boolean>> history)পদ্ধতি রয়েছে।

  2. কন্ট্রোলার উপরোক্ত শ্রেণীর উদাহরণগুলি সরবরাহ করতে সক্ষম যা মানক I / O এর মাধ্যমে যোগাযোগ করে যখন সহায়তামূলক পদ্ধতিগুলি বলা হয় । এটি বলেছে যে উপরের শ্রেণীর সমস্ত দৃষ্টান্ত অগত্যা স্ট্যান্ডার্ড I / O এর সাথে যোগাযোগ করবে না। বটগুলির মধ্যে 3 স্থানীয় জাভা বট হতে পারে (এটি কেবল Playerক্লাসটি ওভাররাইড করে , যেখানে আরও 2 জন অন্য ভাষায় থাকে)

  3. পদ্ধতিগুলিতে সর্বদা একই সংখ্যার আর্গুমেন্ট থাকবে না (তাদের সবসময় কোনও ফেরতের মানও থাকবে না)

  4. আমি চাই চ্যালেঞ্জ-লেখককে আমার কাঠামোর সাথে কাজ করার জন্য যতটা সম্ভব কম কাজ করতে হবে।

আমি এই সমস্যাগুলি সমাধান করতে প্রতিবিম্ব ব্যবহার করার বিরুদ্ধে নই। আমি চ্যালেঞ্জ লেখকের মতো কিছু করার প্রয়োজন বিবেচনা করেছি:

class PlayerComm extends Player {
    private Communicator communicator;
    public PlayerComm(Communicator communicator){
        this.communicator = communicator;
    }
    @Override
    boolean vote(List<List<Boolean>> history){
         return (Boolean)communicator.sendMessage(history);
    }
}

তবে যদি বেশ কয়েকটি পদ্ধতি থাকে তবে এটি বেশ পুনরাবৃত্তি পেতে পারে এবং ধ্রুবক castালাই মজাদার নয়। ( sendMessageএই উদাহরণে একটি পরিবর্তনশীল সংখ্যক Objectআর্গুমেন্ট গ্রহণ করা হবে এবং একটি ফেরত দেওয়া হবে Object)

এই কাজ করতে একটি ভাল উপায় আছে কি?


1
আমি " PlayerComm extends Player" পার্ট সম্পর্কে বিভ্রান্ত । সমস্ত জাভা প্রবেশকারীগুলি কি বাড়িয়ে দিচ্ছে Player, এবং এই PlayerCommশ্রেণিটি জাভাবিহীন প্রবেশকারীদের জন্য অ্যাডাপ্টার?
জিরোওন

হ্যাঁ, এটি ঠিক
নাথান মেরিল

সুতরাং, কৌতূহলের বাইরে ... আপনি কি এর জন্য কোনও ধরণের সুন্দর সমাধান নিয়ে আসতে পেরেছেন?
জিরোওন

নাঃ। আমি যা চাই তা জাভাতে সম্ভব বলে আমি মনে করি না: /
নাথন মেরিল

উত্তর:


1

ঠিক আছে তাই জিনিসগুলি ধীরে ধীরে বেড়েছে এবং আমি নিম্নলিখিত দশটি ক্লাস দিয়ে শেষ করেছি ...

এই পদ্ধতির মূল লাইনটি হ'ল সমস্ত যোগাযোগ Messageক্লাস ব্যবহার করে ঘটে থাকে , অর্থাত গেমটি খেলোয়াড়দের পদ্ধতিগুলিকে সরাসরি ডাকে না তবে সর্বদা আপনার কাঠামো থেকে যোগাযোগকারী শ্রেণি ব্যবহার করে। নেটিভ জাভা ক্লাসগুলির জন্য একটি প্রতিবিম্ব-ভিত্তিক যোগাযোগকারী রয়েছে এবং তারপরে সমস্ত জাভা-না-প্লেয়ারের জন্য একটি কাস্টম যোগাযোগকারী থাকতে হবে। প্যারামিটারটি ফেরত দিয়ে Message<Integer> message = new Message<>("say", Integer.class, "Hello");একটি পদ্ধতিতে একটি বার্তা শুরু করবে । এরপরে এটি কোনও যোগাযোগকারীর কাছে পাঠানো হয় (প্লেয়ারের ধরণের উপর ভিত্তি করে একটি ফ্যাক্টরি ব্যবহার করে উত্পন্ন) যা কমান্ডটি কার্যকর করে।say"Hello"Integer

import java.util.Optional;

public class Game {
    Player player; // In reality you'd have a list here

    public Game() {
        System.out.println("Game starts");
        player = new PlayerOne();
    }

    public void play() {
        Message<Boolean> message1 = new Message<>("x", Boolean.class, true, false, true);
        Message<Integer> message2 = new Message<>("y", Integer.class, "Hello");
        Result result1 = sendMessage(player, message1);
        System.out.println("Response 1: " + result1.getResult());
        Result result2 = sendMessage(player, message2);
        System.out.println("Response 2: " + result2.getResult());
    }

    private Result sendMessage(Player player, Message<?> message1) {
        return Optional.ofNullable(player)
                .map(Game::createCommunicator)
                .map(comm -> comm.executeCommand(message1))
                .get();
    }

    public static void main(String[] args) {
        Game game = new Game();
        game.play();
    }

    private static PlayerCommunicator createCommunicator(Player player) {
        if (player instanceof NativePlayer) {
            return new NativePlayerCommunicator((NativePlayer) player);
        }
        return new ExternalPlayerCommunicator((ExternalPlayer) player);
    }
}

public abstract class Player {}

public class ExternalPlayer extends Player {}

public abstract class NativePlayer extends Player {
    abstract boolean x(Boolean a, Boolean b, Boolean c);
    abstract Integer y(String yParam);
    abstract Void z(Void zParam);
}

public abstract class PlayerCommunicator {
    public abstract Result executeCommand(Message message);
}

import java.lang.reflect.Method;
public class NativePlayerCommunicator extends PlayerCommunicator {
    private NativePlayer player;
    public NativePlayerCommunicator(NativePlayer player) { this.player = player; }
    public Result executeCommand(Message message) {
        try {
            Method method = player.getClass().getDeclaredMethod(message.getMethod(), message.getParamTypes());
            return new Result(method.invoke(player, message.getArguments()));
        } catch (Exception e) { throw new RuntimeException(e); }
    }
}

public class ExternalPlayerCommunicator extends PlayerCommunicator {
    private ExternalPlayer player;
    public ExternalPlayerCommunicator(ExternalPlayer player) { this.player = player; }
    @Override
    public Result executeCommand(Message message) { /* Do some IO stuff */ return null; }
}

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Message<OUT> {
    private final String method;
    private final Class<OUT> returnType;
    private final Object[] arguments;

    public Message(final String method, final Class<OUT> returnType, final Object... arguments) {
        this.method = method;
        this.returnType = returnType;
        this.arguments = arguments;
    }

    public String getMethod() { return method; }
    public Class<OUT> getReturnType() { return returnType; }
    public Object[] getArguments() { return arguments; }

    public Class[] getParamTypes() {
        List<Class> classes = Arrays.stream(arguments).map(Object::getClass).collect(Collectors.toList());
        Class[] classArray = Arrays.copyOf(classes.toArray(), classes.size(), Class[].class);
        return classArray;
    }
}

public class PlayerOne extends NativePlayer {
    @Override
    boolean x(Boolean a, Boolean b, Boolean c) {
        System.out.println(String.format("x called: %b %b %b", a, b, c));
        return a || b || c;
    }

    @Override
    Integer y(String yParam) {
        System.out.println("y called: " + yParam);
        return yParam.length();
    }

    @Override
    Void z(Void zParam) {
        System.out.println("z called");
        return null;
    }
}

public class Result {
    private final Object result;
    public Result(Object result) { this.result = result; }
    public Object getResult() { return result; }
}

(পিএস। আমার মনের অন্যান্য কীওয়ার্ড যে আমি এই মুহূর্তে দরকারী কোনও কিছুর মধ্যে পুরোপুরি পরিমার্জন করতে পারি না: কমান্ড প্যাটার্ন , ভিজিটর প্যাটার্ন , জাভা.ল্যাং.রেফलेक्ट.প্যারামিটারাইজড টাইপ )


আমার লক্ষ্য হ'ল যিনি Playerলেখালেখি থেকে একেবারেই লেখালেখি করেছেন তার প্রয়োজনীয়তা রোধ করা PlayerComm। যোগাযোগকারী ইন্টারফেসগুলি আমার জন্য স্বয়ংক্রিয়ভাবে ingালাই করার সময়, আমি এখনও sendRequest()প্রতিটি পদ্ধতিতে একই ফাংশনটি লেখার একই সমস্যাটিতে চলে আসছি ।
নাথান মেরিল

আমি আমার উত্তর নতুন করে লিখেছি। যাইহোক, আমি এখন বুঝতে পেরেছি যে ফ্যাসাদ প্যাটার্নটি ব্যবহার করা আসলে জাভা প্রবেশের মতো দেখতে অদ্বিতীয় জাভা প্রবেশগুলিতে মোড়ক করে এখানে যাওয়ার উপায় হতে পারে। সুতরাং কিছু যোগাযোগকারী বা প্রতিফলনের সাথে আশেপাশে কোনও বোকামি নেই।
জিরোওন

2
"ঠিক আছে তাই জিনিসগুলি ধীরে ধীরে বেড়েছে এবং আমি নিম্নলিখিত দশটি ক্লাস দিয়ে শেষ করেছি" যদি আমার নিকেল থাকে ...
জ্যাক

ওও, আমার চোখ! যাইহোক আমরা এই 10 টি ক্লাসের সাথে যাওয়ার জন্য একটি বর্গের চিত্র পেতে পারি? অথবা আপনি নিজের মুখের প্যাটার্ন উত্তরটি লিখতে খুব ব্যস্ত?
candied_orange

@ ক্যান্ডিওড ওরেঞ্জ, আসলে আমি মনে করি আমি ইতিমধ্যে এই প্রশ্নের সাথে যথেষ্ট সময় ব্যয় করেছি। আমি এক ধরনের আশা করছি যে অন্য কেউ সম্ভবত সমাধানের ধরণ ব্যবহার করে সমাধানের সংস্করণ দেবে।
জিরোওনে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.